Зачем использовать адрес первого элемента структуры, а не структуры?
Я только что наткнулся на еще одну базу кода на работе, где разработчики последовательно используют адрес первого элемента структур при копировании/сравнении / настройке, а не саму структуру. Вот простой пример.
сначала есть структура типа:
typedef struct {
int a;
int b;
} foo_t;
тогда есть функция, которая делает копию такой структуры:
void bar(foo_t *inp)
{
foo_t l;
...
memcpy(&l.a, &inp->a, sizeof(foo_t));
...
}
Я бы сам не стал писать звонок memcpy
таким образом, и я начал с подозрения, что оригинал разработчики просто не совсем понимали указатели и структуры в C. Однако теперь я видел это в двух несвязанных кодовых базах, без общих разработчиков, поэтому я начинаю сомневаться в себе.
зачем нужно использовать этот стиль?
6 ответов:
вместо этого:
memcpy(&l.a, &inp->a, sizeof(foo_t));
вы можете сделать это:
memcpy(&l, inp, sizeof(foo_t));
хотя это может быть опасно и вводит в заблуждение, оба утверждения на самом деле делают то же самое, что и C гарантирует отсутствие заполнения перед первым элементом структуры.
но лучше всего просто скопировать объекты структуры с помощью простого оператора присваивания:
l = *inp;
почему нужно использовать этот стиль?
мое предположение: невежество или плохо дисциплина.
никто не. Если вас когда-нибудь переезжал
a
в структуре или вы вставили член(ы) перед ним, вы бы ввести память разбивая ошибку.
этот код небезопасен, потому что перестановка элементов структуры может привести к
memcpy
доступ за пределы структуры, если членa
больше не является первым членом.однако вполне возможно, что члены преднамеренно упорядочены в структуре, и программист хочет скопировать только их подмножество,начало С и до конца структуры. Если это так, то код можно сделать безопасным с помощью следующее изменение:
memcpy(&l.a, &inp->a, sizeof(foo_t) - offsetof(foo_t, a));
теперь члены структуры могут быть переставлены в любом порядке и это
memcpy
никогда не выйдет за пределы.
это действительно плохая привычка. Например, в структуре может быть добавлен другой член. Это безумно небрежная привычка, и я с удивлением читаю, что кто-то это сделает.
другие уже заметили это; тот, который меня беспокоит, это:
struct Foo rgFoo [3]; struct Foo *pfoo = &rgFoo [0];
вместо
struct Foo *pfoo = rgfoo;
Почему deref массив по индексу, а затем снова взять адрес? Это уже адрес, единственное отличие состоит в том, что pfoo технически
struct Foo *const,
не
struct Foo *.
тем не менее, я видел первый все время.
на самом деле, есть один законный вариант использования для: построения иерархии классов.
при обработке структур как экземпляров класса первый член (т. е. смещение 0) обычно будет экземпляром супертипа... если супертип существует. Это позволяет простому приведению перемещаться между использованием подтипа и супертипа. Очень полезно.
на заметке Даррена Стоуна о намерении, это ожидается при выполнении OO в C язык.
в любом другом случае, Я бы предложил избежать этого шаблона и получить доступ к члену напрямую вместо этого, по уже упомянутым причинам.