Это потому, что вызов printf
помещает всю структуру xyz
в стек, и эта структура (в данном случае) состоит из двух целых чисел.xyz.a
в этом случае игнорируется, поскольку он находится за пределами области стека, о которой заботится printf
.
Хотя поведение не определено (a) , так что может произойти что угодноСлучай можно объяснить, потому что оператор printf("%d %d",xyz,xyz.a);
, вероятно, помещает xyz
и xyz.a
в стек что-то вроде:
xyz.a | 10 | |
xyz | 20 | | Stack grows downward.
| 10 | V
и самого кода printf
, потому что ему присвоено два %d
s, напечатает 10 внизу и 20. Иными словами, это несоответствие между строкой формата и параметрами.
Когда вы добавляете еще один %d
, он печатает то, что считаеттретий аргумент (но на самом деле второй), верхние 10 в приведенной выше диаграмме.
Я должен отметить, что полагаться на такое поведение не очень хорошая идея.Это может измениться, когда вы переключаете компиляторы, версии компилятора или, возможно, даже в нечетные дни: -)
Хорошие компиляторы, такие как gcc
, на самом деле заглядывают в аргументы printf
, чтобы уловить это как потенциалошибка:
pax$ cat qq.c
#include<stdio.h>
struct abc { int a; int b; } xyz;
int main (void) {
xyz.a=10;
xyz.b=20;
printf("%d %d",xyz,xyz.a);
return 0;
}
pax$ gcc -Wall -o qq qq.c
qq.c: In function 'main':
qq.c:6: warning: format '%d' expects type 'int',
but argument 2 has type 'struct abc'
qq.c:6: warning: format '%d' expects type 'int',
but argument 2 has type 'struct abc'
(a) Начиная с c99, раздел 7.19.6.1/9
: Если какой-либо аргумент не является правильным типом для соответствующей спецификации преобразования, поведениене определено.