#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
。
对此有何解释?
答案 0 :(得分:15)
这是因为对printf
的调用正在将整个结构 xyz
推送到堆栈上,并且该结构(在本例中)由两个整数组成。在这种情况下xyz.a
被忽略,因为它超出了printf
关心的堆栈区域。
虽然行为未定义(a)以便可以发生任何事情,但可以解释这种特殊情况,因为printf("%d %d",xyz,xyz.a);
语句可能会推送xyz
和{{1}堆栈之类的东西:
xyz.a
和xyz.a | 10 | |
xyz | 20 | | Stack grows downward.
| 10 | V
代码本身,因为它已被赋予两个printf
,将打印底部的10和20.换句话说,它是格式字符串和格式字符串之间的不匹配参数。
当你添加另一个%d
时,它会打印它认为是第三个参数(但实际上是第二个参数),上图中的前10个。
我应该提到依赖这种行为并不是一个好主意。当你切换编译器,编译器的版本,甚至可能在奇数天时,它可能会改变: - )
像%d
这样的优秀编译器实际上会查看gcc
个参数,将其视为潜在错误:
printf
(a)从c99开始,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'
部分:如果任何参数不是相应转换规范的正确类型,则行为未定义。 < / p>
答案 1 :(得分:2)
您已调用未定义的行为; 允许任何结果。
7.19.6.1 fprintf功能
...
9如果转换规范无效,则行为未定义。 248) 如果有任何参数是 不是相应转换规范的正确类型,行为是 未定义。的
强调我的。 xyz
的类型为struct abc
,但printf
期望该参数为int
类型。
paxdiablo的回答是关于这样的结果可能如何发生的一个体面的事后判断,但这仅适用于您的具体情况。更改关于代码或翻译环境或执行环境的任何,结果可能会有所不同。