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

Что делает ((имя структуры *) 0) → член) в C?

Что делает ((имя структуры *) 0) → член) в C?

Фактический оператор C, с которым я столкнулся, был следующим:

(char *) &((struct name *)0)->member)
4b9b3361

Ответ 1

Это трюк для получения смещения члена struct, называемого member. Идея этого подхода заключается в том, чтобы компилятор вычислил адрес member, предполагая, что сама структура находится по адресу нуль.

Использование offsetof предлагает более читаемую альтернативу этому синтаксису:

size_t offset = offsetof(struct name, member);

Ответ 2

(struct name *)0 отличает 0 указателем на struct name.
&((struct name *)0)->member) получает адрес члена member.
(char *) &((struct name *)0)->member) отправляет этот адрес на char *.

Если кто-то считает, что указанное выше выражение разыменовывает указатель NULL, то обратите внимание, что здесь не существует разыменования. Все это для получения адреса члена number.

Ответ 3

(struct name*)0 дает указатель на структуру.

((struct name*)0)->member дает вам член структуры, на который указывает указатель.

Добавление & дает вам адрес этого члена и, наконец,

(char *) - передать полученный адрес указателю char.

Ответ 4

Во многих компиляторах приведенное выше выражение даст char*, который, хотя он не является допустимым указателем, имеет одно или оба из следующих свойств:

  • Приведение указателя непосредственно к целочисленному типу приведет к смещению указанного элемента внутри структуры.

  • Вычитание (char*)0 из указателя приведет к смещению указанного элемента внутри структуры.

Обратите внимание, что стандарт C не предъявляет никаких требований относительно того, что может произойти, если код формирует недопустимое значение указателя с помощью вышеуказанных средств или любого другого, даже если код не пытается разыменовать указатель. Хотя многие компиляторы производят указатели с указанными качествами, такое поведение не является универсальным. Даже на платформах, где существует четкая естественная связь между указателями и целыми числами, некоторые производители компиляторов могут решить, что, если программы ведут себя так, как подразумевается такими отношениями, было бы более "эффективно" вместо этого, чтобы компилятор предполагал, что программа никогда не будет получать входные данные, которые приведут к генерации недействительных указателей и, следовательно, следует исключить любой код, который будет иметь значение только в том случае, если такие входы были опущены.