int func(int **a)
{
*a = NULL;
return 1234;
}
int main()
{
int x = 0, *ptr = &x;
*ptr = func(&ptr); // <-???
printf("%d\n", x); // print '1234'
printf("%p\n", ptr); // print 'nil'
return 0;
}
Is this an example of undefined behavior or has to do with sequence points? why the line:
*ptr = func(&ptr);
doesn't behave like:
*NULL = 1234;
EDIT: I forgot to mention that I get the output '1234' and 'nil' with gcc 4.7.
Since there is no sequence point between evaluations of the left and right hand sides of the assignment operator, it is not specified whether *ptr
or func(&ptr)
is evaluated first. Thus it is not guaranteed that the evaluation of *ptr
is allowed, and the program has undefined behaviour.
The language does not guarantee you that the right-hand side subexpression func(&ptr)
in
*ptr = func(&ptr);
is evaluated first, and the left-hand side subexpression *ptr
is evaluated later (which is apparently what you expected to happen). The left-hand side can legally be evaluated first, before call to func
. And this is exactly what happened in your case: *ptr
got evaluated before the call, when ptr
was still pointing to x
. After that the assignment destination became finalized (i.e. it became known that the code will assign to x
). Once it happens, changing ptr
no longer changes the assignment destination.
So, the immediate behavior of your code is unspecified due to unspecified order of evaluation. However, one possible evaluation schedule leads to undefined behavior by causing a null pointer dereference. This means that in general case the behavior is undefined.
If I had to model the behavior of this code in terms of C++ language, I'd say that the process of evaluation in this case can be split into these essential steps
1a. int &lhs = *ptr; // evaluate the left-hand side
1b. int rhs = func(&ptr); // evaluate the right-hand side
2. lhs = rhs; // perform the actual assignment
(Even though C language does not have references, internally it uses the same concept of "run-time bound lvalue" to store the result of evaluation of left-hand side of assignment.) The language specification allows enough freedom to make steps 1a and 1b to occur in any order. You expected 1b to occur first, while your compiler decided to start with 1a.
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