开发者

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);
}

The output of of the above program is 10 20.

If I add anot开发者_如何学JAVAher printf statement as

printf("%d %d %d", xyz, xyz.a, xyz.b);

the output comes 10 20 10.

What's the explanation for this?


It's because the call to printf is pushing the entire structure xyz onto the stack and that structure (in this case) consists of the two integers. The xyz.a in that case is ignored since it's beyond the stack area that printf cares about.

Although the behaviour is undefined(a) so that anything can happen, this particular case can be explained because the printf("%d %d",xyz,xyz.a); statement probably pushes xyz and xyz.a on to the stack something like:

xyz.a | 10 |    |
xyz   | 20 |    | Stack grows downward.
      | 10 |    V

and the printf code itself, because it's been given two %d's, will print the 10 at the bottom and the 20. In other words, it's a mismatch between the format string and the parameters.

When you add another %d, it prints what it thinks is the third argument (but is actually the second), the top 10 in the above diagram.

I should mention that relying on this behaviour is not a good idea. It may change when you switch compilers, versions of the compiler, or possibly even on odd-numbered days :-)

Good compilers like gcc actually look inside the printf arguments to catch this as a potential error:

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) From c99, section 7.19.6.1/9: If any argument is not the correct type for the corresponding conversion specification, the behavior is undefined.


You've invoked undefined behavior; any result is allowed.

7.19.6.1 The fprintf function
...
9 If a conversion specification is invalid, the behavior is undefined.248) If any argument is not the correct type for the corresponding conversion specification, the behavior is undefined.

Emphasis mine. xyz is of type struct abc, but printf is expecting that argument to be type int.

paxdiablo's answer is a decent postmortem of how such a result may occur, but that's only applicable to your specific circumstances. Change anything about the code or the translation environment or the execution environment, and the result will probably be different.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜