Few days ago I was asked question what would be the output of this code:
#include <stdio.h> int main() { int a = 5; printf("%d %d %d %d\n",a++,a++,++a,a++); return 0; }
Nothing special, right? But C standard do not specify how printf evaluates it’s parameters, so it’s left up to the C compiler and here the fun part starts.
Old C compilers would be a bit more predictable as they would start evaluating from the top of the stack to the bottom i.e. right to left, but the new ones heavy optimize and try to execute some instructions in parallel, so the only certain thing is that at the printf “;” point of synchronization “a” would be incremented 4 time, but nobody knows in what order.
Compiled with GCC/Code Blocks the output is:
Again nobody guarantee that if you re-compile on different computer /CPU the result will be same!
Even changing the code with one more line like enter the value of a with scanf leads to different result:
So good practice will be to avoid any calculations inside printf and to search logic there. Do these separately where compiler has to stick to C standard and rules.
Mar 07, 2019 @ 14:03:45
Of course its nothing special – its just undefined behaviour as described in standard.
You do mention that the order of function call argument evaluation its not specified (perhaps adding a link to the article about sequence points could be beneficial to some readers), but after that you claim that “one should avoid calculations inside printf” which is simply misleading.
1. Its not limited to printf – it applies to any function call
2. Its not about calculations, its about expressions with side-effects
3. Its not limited to function calls –
This is perfectly safe (assuming correct format string):
printf(“…”, a+1, b-2, a*7);
x = a++ – ++a; // this is UB and must be avoided