Подтвердить что ты не робот

Зачем использовать адрес первого элемента структуры, а не структуру?

Я только что нашел еще одну базу кода на работе, где разработчики последовательно используют адрес первого элемента structs при копировании/сравнении/настройке, а не в самой структуре. Вот простой пример.

Сначала введите тип структуры:

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. Однако теперь я видел это в двух несвязанные базы кода, без общих разработчиков, поэтому я начинаю сомневаться в себе.

Почему нужно использовать этот стиль?

4b9b3361

Ответ 1

Никто не должен этого делать. Если вы перестраиваете элементы структуры, у вас проблемы.

Ответ 2

Вместо этого:

memcpy(&l.a, &inp->a, sizeof(foo_t));

вы можете сделать это:

memcpy(&l, inp, sizeof(foo_t));

В то время как это может быть опасно и вводить в заблуждение, оба утверждения фактически делают то же самое здесь, что C гарантирует, что перед первым элементом структуры не будет прокладка.

Но лучше всего просто скопировать объекты структуры с помощью простого оператора присваивания:

l = *inp;

Почему нужно использовать этот стиль?

Мое предположение: невежество или плохая дисциплина.

Ответ 3

Не было бы. Если вы когда-либо перемещали a в структуру или вы вставляли ее элементы (ы), вы вводили ошибку памяти.

Ответ 4

Этот код небезопасен, потому что переупорядочение элементов структуры может привести к тому, что memcpy получит доступ за пределы структуры, если член a уже не первый член.

Однако, возможно, что члены намеренно упорядочены внутри структуры, а программист только хочет скопировать подмножество из них, начиная с члена a и запуская до конца структуры. В этом случае код можно сделать безопасным со следующим изменением:

    memcpy(&l.a, &inp->a, sizeof(foo_t) - offsetof(foo_t, a));

Теперь члены структуры могут быть перегруппированы в любой порядок, и этот memcpy никогда не выйдет за рамки.

Ответ 5

Это очень плохая привычка. Например, структура может иметь, например, другой член. Это безумно неосторожная привычка, и я с удивлением узнаю, что кто-то это сделает.

Другие уже отметили это; тот, который меня беспокоит, таков:
struct Foo rgFoo [3];
struct Foo *pfoo = &rgFoo [0];

вместо

struct Foo *pfoo = rgfoo;

Зачем выделять массив по индексу, а затем снова принимать адрес? Это уже адрес, единственное отличие в том, что pfoo технически

struct Foo *const, 

not

struct Foo *.  

Но я все время видел первый.

Ответ 6

На самом деле для этого есть один законный прецедент: построение иерархии классов.

При обработке структур как экземпляров класса первый член (т.е. смещение 0) обычно будет экземпляром супертипа... если существует супертип. Это позволяет простому движению перемещаться между использованием подтипа и супертипа. Очень полезно.

В отношении Darren Stone обратите внимание на намерение, это ожидается при выполнении OO на языке C.

В любом другом случае я бы предложил избежать этого шаблона и получить доступ к элементу напрямую, по причинам, уже указанным.