Anatoly
Anatoly

Reputation: 5243

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.

Upvotes: 6

Views: 8688

Answers (5)

chqrlie
chqrlie

Reputation: 144695

This sentence is quite confusing: test(i++,i++); it isn't valid because the behaviour is undefined according to K&R p202 .

The truth is this statement has always been invalid in C. From the original specification of C by Kernighan and Ritchie in their book The C programming language to the latest C11 Standard published a few years ago, including the older C99 Standard and the obsolete C89 standard also known as ANSI C. Just not for the reason stated.

The order in which the aguments to the function test are evaluated is unspecified, but this is not the problem here: both expressions modify the same variable and there is no sequence point between function argument evaluation. So it does not matter how you achieve side effects in the expressions used for the arguments, you invoke undefined behaviour. The compiler may generate code, but the rocket may explode upon take-off.

Upvotes: 4

Sourav Ghosh
Sourav Ghosh

Reputation: 134316

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.

Upvotes: 11

phoxis
phoxis

Reputation: 61910

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.

Upvotes: 7

Michael F
Michael F

Reputation: 40830

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.

Upvotes: 4

Jack Whitham
Jack Whitham

Reputation: 609

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

Upvotes: 12

Related Questions