Есть ли недостатки в передаче структур по значению в 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();
По некоторым причинам, я думаю, что большинство людей инстинктивно заставляют exam_data брать указатель на структурный объект, но я не понимаю, почему. Он по-прежнему получает указатель и целое число, просто гораздо яснее, что они идут вместе. А в случае с get_data невозможно все испортить, как я описал ранее, так как для длины нет входного значения и должна быть возвращаемая длина.
gettimeofday
), вместо этого используют указатели, и люди берут это в качестве примера.
void examine data(const struct blob)
это неверно.