During my preparation to exam on ANSI C I have encountered the following question -
Is following statement valid?
If not, please make required changes to make it valid.
The original statement is: test(i++,i++);
it isn't valid because the behaviour is undefined according to K&R p202
The order of evaluation of arguments is unspecified
But can I change it to the following statement? test(i+=2, i+=3)
?
The problem that I haven't seen such record in K&R or any other source. But XCode compile it and run without any warning.
Both are valid statements, i.e. legal C, and in both cases, the behavior is undefined.
To add up to the existing answers, the key point is, the statement
test(i+=2, i+=3)
invokes undefined behavior as much as
test(i++,i++);
because, in both the cases, there is no sequence point scheduled for comma separator in function parameter list and hence, you end up modifying the value of the same variable twice in the scope of a single sequence point. This invokes undefined behaviour.
Statements are syntactically valid, both before and after the change. But still the problem will remain. If you are modifying an object in the argument, and the order of evaluation is unspecified.
C99 Section 6.5.2.2 Paragraph 10
The order of evaluation of the function designator,the actual arguments, and subexpressions within the actual arguments is unspecified, but there is a sequence point before the actual call.
As per Section 3.4.4 Paragraph 1
unspecified behaviour
use of an unspecified value, or other behavior where this International Standard provides two or more possibilities and imposes no further requirements on which is chosen in any instance.
On the other hand Section 3.4.3 Paragraph 1 tells
undefined behaviour
behavior,upon use of a nonportable or erroneous program construct or of erroneous data, for which this International Standard imposes no requirement
In the case of the order or evaluation, it can be done in any order, depending on how the compiler generates the code, it might store in-memory in any order and also may pass the arguments through register. Once the code is generated, the binary will behave same everywhere. Therefore for one single binary the results will be identical every time, but depending on the decision of the compiler things can change.
The best idea is to avoid anything which seems to be incorrect or fancy. When in doubt, possibly it is an undefined, unspecified, implementation-defined behaviour. Therefore you can make the same thing unambiguous and deterministic as follows.
test (i, i+1);
i += 2;
OR
test (i+1, i);
i+= 2;
Depending on what order you want.
As others have already noted, the behaviour in both cases is undefined, even if the code is syntactically valid in both cases. I assume the question uses "valid" to mean "correct", as in a strictly conforming C program. To make the statement correct, you must first know/derive its intent.
That could in fact be impossible without some external source telling you exactly what that intent is, but let's assume for the sake of argument that the programmer wishes to invoke the function test
with the parameters (i+1, i+2)
(in order of appearance). It would be best to communicate this intent by simply:
test (i + 1, i + 2);
i += 2;
avoiding any ill effects introduced by the unspecified order of evaluation of function arguments.
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