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?
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With