是什么解释了这个C代码的输出?

时间:2011-01-30 12:02:01

标签: c

#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

对此有何解释?

2 个答案:

答案 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的回答是关于这样的结果可能如何发生的一个体面的事后判断,但这仅适用于您的具体情况。更改关于代码或翻译环境或执行环境的任何,结果可能会有所不同。