[英]What explains the output of this C code?
#include <stdio.h>
struct abc{
int a;
int b;
} xyz;
int main()
{
xyz.a = 10;
xyz.b = 20;
printf("%d %d", xyz, xyz.a);
}
上面程序的输出是10 20
。
如果我添加另一个printf
语句为
printf("%d %d %d", xyz, xyz.a, xyz.b);
输出为10 20 10
。
这有什么解释?
这是因为对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
并且由于给了两个%d
,因此printf
代码本身将在底部打印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
节: 如果任何参数不是对应转换规范的正确类型,则行为未定义。
您已经调用了未定义的行为 ; 任何结果都是允许的。
7.19.6.1 fprintf函数
...
9如果转换规范无效,则行为未定义。 248) 如果任何参数都不是对应转换规范的正确类型,则行为未定义。
强调我的。 xyz
的类型为struct abc
,但printf
期望该参数的类型为int
。
paxdiablo的答案是对这种结果可能发生的方式进行的事后分析,但这仅适用于您的特定情况。 更改任何有关代码,翻译环境或执行环境的内容,结果可能会有所不同。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.