Спасибо за размещение вашего кода. Теперь я вижу проблему. Это из-за набивки. Для остроумия:
printf("sizeof(char): %d\n", sizeof(char));
printf("sizeof(short): %d\n", sizeof(short));
printf("sizeof(int): %d\n", sizeof(int));
printf("sizeof(struct st): %d\n", sizeof(struct st));
На моей машине это печатает
1
2
4
8
Вы можете подумать, разве sizeof(struct st)
не должно быть 1 + 2 + 4 = 7
? Это, конечно, разумная мысль, но из-за проблем с выравниванием между a
и c
есть отступы. Следовательно, в памяти структура выглядит следующим образом (относительно первого байта структуры):
0x00000000: char a
0x00000001: padding
0x00000002: first byte of short c
0x00000003: second byte of short c
0x00000004: first byte of int b
0x00000005: second byte of int b
0x00000006: third byte of int b
0x00000007: fourth byte of int b
Следовательно (относительно &s1
):
&s1.b - 1 is ((long)&s1.b) - sizeof(int) = 4 - 4 = 0 = &s1
Вот почему &s1
и &s1.b - 1
будут печатать один и тот же адрес. В частности, если
&s1 = 0x804a01c
тогда
&s1.b = 0x804a01c + 0x00000004 = 0x804a020
и
&s1.b - 1 = 0x804a020 - 0x00000004 = 0x804a01c
и
&s1.b - 2 = 0x804a020 - 0x00000008 = 0x804a018
Обратите внимание, наконец, что это поведение, зависящее от реализации. Это не портативный!