Начнём с последней строки:
printf("%d",*(int*)((char*)na + (unsigned int) & (((struct name *)NULL)->b)));
Позволяет интерпретировать:
(unsigned int) & (( (struct name *)NULL)->b)
фактически литье & (( (struct name *)NULL)->b)
в unsigned int
.
& (( (struct name *)NULL)->b)
является адрес (т.е. он дает указатель):
(( (struct name *)NULL)->b)
который фактически является смещение b
(как name.b
) от NULL (0), который составляет 4 байта (при условии long
является 4 байта) и преобразован в указатель int, дает вам 2 (предполагается, что int
- 2 байта).
Если вместо NULL
было бы указателем на 0xFFFF0000
, то &(ptr->b)
бы 0xFFFF0002
. Но это больше похоже на &(0 -> b)
, поэтому его 0x00000002
.
Итак, (unsigned int) & (( (struct name *)NULL)->b) == 2
(или, может быть, 1 или 4, в зависимости от машины).
Остальное просто: *(int*)((char*)na + 2
будет указывать на re->b
. Поэтому он должен распечатать 4 (что было инициализировано в коде, r re ={3,4,5};
).
P.S: даже если (unsigned int) & (((struct name *)NULL)->b) != 2
(возможно, это 1, 4 или 8) - он все равно должен печатать 4, потому что тогда он использует то же смещение, чтобы получить значение.
Вы знаете, что 'main' имеет возвращаемый тип' int' в C (и C++)? – Deduplicator
Эта точная программа была опубликована 3 года назад, я думаю, это обычная книга! –