Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why "%I64d" is giving strange output when it is used multiple times in same format string?

Tags:

c++

c

While I was solving a programming problem on codeforces, I found that when the format specifier "%I64d" was used multiple times in same format string like:

long long int a, b, c;
a = 1, b = 3, c = 5; 
printf("%I64d %I64d %I64d\n", a, b, c);

the output was

                                                               1                                                                0                                                                3 

However when I separated each specifier, like:

long long int a, b, c;
a = 1, b = 3, c = 5;
printf("%I64d ", a);
printf("%I64d ", b);
printf("%I64d ", c);
puts("");

the output was, as expected:

                                                           1                                                                3                                                                5 

Here is the ideone link to see above code snippets in action: http://ideone.com/f2udRB

Please help me to understand why this is happening? If this is undefined behaviour, how such an output is shown? How can I understand the reasons when sometimes such unexpected outputs are shown?

like image 633
Pradyumna Newalkar Avatar asked Dec 08 '22 20:12

Pradyumna Newalkar


2 Answers

With the format string %I64d printf() expects a 4-byte number on the stack, since with GNU printf I means, "use alternative output digits" and the 64 means "pad to 64 chars". The remaining d stands for an signed 32-bit integer.

But you are pushing 8-byte numbers, since a, b, c are of type long long.

The numbers are below 2^32, so on the stack you see (in 4-byte-steps)

1 0 3 0 5 0

Only the first 3 numbers are interpreted by printf, the rest is discarded. When you use %lld, printf() correctly interprets the stack data as 8-byte numbers.

like image 53
Ctx Avatar answered Dec 10 '22 09:12

Ctx


Please help me to understand why this is happening? If this is undefined behaviour, how such an output is shown?

Yes, the behavior is undefined, but the reason of different output is due to calling conventions. The ideone compiler is running at 32-bit, which means that parameters are passed on stack (according to the System V ABI) instead of registers. You may see that dissassembly of the code shows like:

    push    0
    push    5
    push    0
    push    3
    push    0
    push    1
    push    OFFSET FLAT:.LC0
    call    printf

The second code snippet is different because you passing just one argument each time, so it gets the correct (that is, the first one) value.

like image 28
Grzegorz Szpetkowski Avatar answered Dec 10 '22 10:12

Grzegorz Szpetkowski