Hi all,
Why do I get a warning from gcc with the following program?
[test]$ cat test.c
#include <stdio.h>
int f(int n)
{
return n;
}
int main(void)
{
int n = 0;
printf("%i\n", f(n++) + n);
return 0;
}
[test]$ gcc -Wall test.c
test.c: In function ‘main’:
test.c:13: warning: operation on ‘n’ may be undefined
Yes, the operation on 'n' may be undefined. 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."
The printf() call in your call does not modify the value of 'n' more
than once. The expression 'n++' modifies 'n' exactly once, and uses
the original value of 'n' only for the purpose of computing the new
value. But the '+ n' subexpression attempts to access the prior value
of 'n' in a way that is not used in the computation of the new value.
One of the sequence point cases is defined as: "The point of calling a
function, after evaluating its arguments." If I got it right, that rule
can be applied to `f(n++)' which is evaluated before `n' since addition
is left associative. I can't see the ambiguity here.
No, you are wrong, associatively has nothing at all to do with order
of evaluation. Only sequence points impose an order of evaluation.
August
(I would never write this kind of code in practice, but it's good to
know how the standard is defined.)
Let's take an example that doesn't have undefined behavior:
#include <stdio.h>
int f1(void)
{
puts("function 1\n");
return 1;
}
int f2(void)
{
puts("function 1\n");
return 2;
}
int main(void)
{
printf("the sum is %d\n", f1() + f2());
return 0;
}
This function does not define or contain any objects at all, so the
paragraph I quoted from the standard certainly does not apply.
Because the order of evaluation between sequence points is
unspecified, the output could be either of the following two
sequences, and must be one of the two:
function 1
function 2
the sum is 3
....or:
function 2
function 1
the sum is 3
In fact, it may change between one and the other if you change the
settings you use to invoke your compiler, for example enable or
disable optimization.
If just so happens that if your compiler evaluates the subexpression
'f(n++)' first, the result is defined because there is a sequence
point imposed by calling the function before the '+ n' subexpression
reads the value of 'n' again.
But if your compiler evaluates 'n' in the '+ n' subexpression before
evaluating the 'f(n++)' subexpression, there is no sequence point
between the unrelated read and the modification, the behavior is
undefined.
Finally, since the order of evaluation is something the standard
states is unspecified, it means that the compiler does not have to
tell you which order it uses, and is free to change it based on
settings, the day of the week, or the phase of the moon.
Since one of the unspecified paths generates undefined behavior, the
whole thing should be treated as undefined.