Explanation of output of C code
I came across this code:
#include<stdio.h>
void main()
{
int x;
float t;
scanf("%f",&t);
printf("%d\n",t);
x=90;
printf("%f\n",x);
{
x=1;
printf("%f\n",x);
{
x=30;
printf("%f\n",x);
}
printf("%f\n",x);
}
printf("%f\n",x);
}
Glancing at it I thought of it as some undefined output as quoted in standards:
A warning: printf uses its first argument to decide how many arguments follow and what their type is. It will get confused, and you will get wrong answers, if there are not enough arguments of if they are the wrong type.
But the output didn't let me leave this question without giving it second thought.
(input given is 23).23
0
23.000000
23.000000
23.000000
23.000000
23.000000
Why always 23.00000? What is the compiler actually trying to do here? Instead of messing around with the value stored at x
, why does it print the value of t
? Does it have an开发者_Python百科y explanation, because there seems something defined about this undefined output (pun intended).
Edit:
I am using gcc compiler on 32 bit machine.
The program behavior is undefined, the compiler is permitted to do anything at all.
That said, I am able to reproduce this behavior on my system and a glance at the assembly output shows what happens:
printf("%d\n",t);
begins by loading the floating point value from t
into the CPU register %xmm0
which is used on my platform to pass floating-point arguments to functions. That register is not accessed by this call to printf()
, since it is looking for an integer input instead.
None of the subsequent calls to printf()
load any values into %xmm0
, since you're not passing any floating-point values into printf or into any other function. But when each printf
encounters %f
in its format string, it reads from %xmm0
, which still contains 23.0
Assembly output, from CLang, using a simpler program with float t = 23.0;
.LCPI0_0:
.quad 4627167142146473984 # double 2.300000e+01
...
movl $.L.str, %edi # .L.str is "%d\n"
movsd .LCPI0_0(%rip), %xmm0 # 23.0 stored in xmm0 here
movb $1, %al
callq printf # this printf will print %esi
movl $90, %esi # 90 stored in %esi here
movl $.L.str1, %edi # .L.str1 is "%f\n"
xorb %al, %al
callq printf # but this printf will print %xmm0
If you really want to know what is producing the behavior here, you need to look at the assembly code this (completely broken) C code is being translated to for your particular compiler and CPU.
精彩评论