开发者

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.

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜