Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is following statement valid in ANSI C? Is it valid at all?

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.

like image 417
Anatoly Avatar asked May 08 '15 10:05

Anatoly


4 Answers

Both are valid statements, i.e. legal C, and in both cases, the behavior is undefined.

like image 118
Jack Whitham Avatar answered Nov 15 '22 10:11

Jack Whitham


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.

like image 35
Sourav Ghosh Avatar answered Nov 15 '22 11:11

Sourav Ghosh


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.

like image 38
phoxis Avatar answered Nov 15 '22 12:11

phoxis


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.

like image 42
Michael Foukarakis Avatar answered Nov 15 '22 12:11

Michael Foukarakis