#include <stdio.h>
struct abc{
int a;
int b;
} xyz;
int main()
{
xyz.a = 10;
xyz.b = 20;
printf("%d %d", xyz, xyz.a);
}
Run Code Online (Sandbox Code Playgroud)
上述程序的输出是10 20.
如果我添加另一个printf语句为
printf("%d %d %d", xyz, xyz.a, xyz.b);
Run Code Online (Sandbox Code Playgroud)
输出来了10 20 10.
对此有何解释?
pax*_*blo 15
这是因为调用printf将整个结构 xyz推送到堆栈上,并且该结构(在本例中)由两个整数组成.的xyz.a,因为它超出了该堆栈区在这种情况下被忽略printf关心.
虽然这种行为是未定义(一)让任何事情都可能发生,这种特殊情况下可以解释,因为printf("%d %d",xyz,xyz.a);声明可能推xyz及xyz.a到堆栈是这样的:
xyz.a | 10 | |
xyz | 20 | | Stack grows downward.
| 10 | V
Run Code Online (Sandbox Code Playgroud)
和printf代码本身,因为它被赋予了两个%d,将在底部打印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'
Run Code Online (Sandbox Code Playgroud)
(a)从c99,section 7.19.6.1/9:如果任何参数不是相应转换规范的正确类型,则行为未定义.