Our class was asked this question by the C programming prof:
You are given the code:
int x=1;
printf("%d",++x,x+1);
What output will it always produce ?
Most students said undefined behavior. Can anyone help me understand why it is so?
Thanks for the edit and the answers but I'm still confused.
printf("%f\n",0); Above line of code is undefined behavior.
Unspecified behavior is different from undefined behavior. The latter is typically a result of an erroneous program construct or data, and no requirements are placed on the translation or execution of such constructs.
C has no specific undefined value. A function that wants to return an undefined value might indicate failure. Sometimes -1 is failure, sometimes 0 is failure, sometimes 0 is success; one has to look up the documentation to know exactly which. For a pointer, the undefined value is often pointer 0, the NULL pointer.
In computer programming, undefined behavior (UB) is the result of executing a program whose behavior is prescribed to be unpredictable, in the language specification to which the computer code adheres.
The output is likely to be 2 in every reasonable case. In reality, what you have is undefined behavior though.
Specifically, the standard says:
Between the previous and next sequence point an object shall have its stored value modified at most once by the evaluation of an expression. Furthermore, the prior value shall be read only to determine the value to be stored.
There is a sequence point before evaluating the arguments to a function, and a sequence point after all the arguments have been evaluated (but the function not yet called). Between those two (i.e., while the arguments are being evaluated) there is not a sequence point (unless an argument is an expression includes one internally, such as using the &&
||
or ,
operator).
That means the call to printf
is reading the prior value both to determine the value being stored (i.e., the ++x
) and to determine the value of the second argument (i.e., the x+1
). This clearly violates the requirement quoted above, resulting in undefined behavior.
The fact that you've provided an extra argument for which no conversion specifier is given does not result in undefined behavior. If you supply fewer arguments that conversion specifiers, or if the (promoted) type of the argument disagrees with that of the conversion specifier you get undefined behavior -- but passing an extra parameter does not.
Any time the behavior of a program is undefined, anything can happen — the classical phrase is that "demons may fly out of your nose" — although most implementations don't go that far.
The arguments of a function are conceptually evaluated in parallel (the technical term is that there is no sequence point between their evaluation). That means the expressions ++x
and x+1
may be evaluated in this order, in the opposite order, or in some interleaved way. When you modify a variable and try to access its value in parallel, the behavior is undefined.
With many implementations, the arguments are evaluated in sequence (though not always from left to right). So you're unlikely to see anything but 2 in the real world.
However, a compiler could generate code like this:
r1
. x+1
by adding 1 to r1
.++x
by adding 1 to r1
. That's ok because x
has been loaded into r1
. Given how the compiler was designed, step 2 cannot have modified r1
, because that could only happen if x
was read as well as written between two sequence points. Which is forbidden by the C standard.r1
into x
.And on this (hypothetical, but correct) compiler, the program would print 3.
(EDIT: passing an extra argument to printf
is correct (§7.19.6.1-2 in N1256; thanks to Prasoon Saurav) for pointing this out. Also: added an example.)
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