Есть ли недостатки для передачи структур по значению в C, а не для передачи указателя?
Если структура велика, очевидно, что для копирования большого количества данных явно характерен аспект, но для небольшой структуры она должна быть в основном такой же, как передача нескольких значений функции.
Возможно, это еще более интересно при использовании в качестве возвращаемых значений. C имеет только одно возвращаемые значения из функций, но вам часто требуется несколько. Поэтому простое решение состоит в том, чтобы поместить их в структуру и вернуть это.
Есть ли какие-либо причины для этого или против этого?
Так как для всех это может быть не очевидно, о чем я говорю, я приведу простой пример.
Если вы программируете на C, вы рано или поздно начнете писать функции, которые выглядят следующим образом:
void examine_data(const char *ptr, size_t len)
{
...
}
char *p = ...;
size_t l = ...;
examine_data(p, l);
Это не проблема. Единственная проблема заключается в том, что вы должны согласиться с вашим сотрудником, в котором порядок параметров должен быть таким, чтобы вы использовали одно и то же соглашение во всех функциях.
Но что происходит, когда вы хотите вернуть такую же информацию? Обычно вы получаете что-то вроде этого:
char *get_data(size_t *len);
{
...
*len = ...datalen...;
return ...data...;
}
size_t len;
char *p = get_data(&len);
Это прекрасно работает, но гораздо более проблематично. Возвращаемое значение является возвращаемым значением, за исключением того, что в этой реализации это не так. Нельзя сказать из вышеизложенного, что функция get_data не позволяет смотреть на то, что указывает len. И нет ничего, что заставило компилятор проверить, действительно ли значение возвращается через этот указатель. Итак, в следующем месяце, когда кто-то другой изменяет код, не понимая его должным образом (потому что он не читал документацию?), Он разбивается, не заметив никого, или он случайно начинает сбой.
Итак, решение, которое я предлагаю, это простая структура
struct blob { char *ptr; size_t len; }
Примеры можно переписать следующим образом:
void examine_data(const struct blob data)
{
... use data.tr and data.len ...
}
struct blob = { .ptr = ..., .len = ... };
examine_data(blob);
struct blob get_data(void);
{
...
return (struct blob){ .ptr = ...data..., .len = ...len... };
}
struct blob data = get_data();
По какой-то причине, я думаю, что большинство людей инстинктивно сделают make_data, чтобы сделать указатель на struct blob, но я не понимаю, почему. Он по-прежнему получает указатель и целое число, но гораздо более ясно, что они идут вместе. И в случае get_data невозможно испортить способ, который я описал ранее, поскольку для длины нет входного значения, и должна быть возвращенная длина.