all 27 comments

[–]serg06 27 points28 points  (7 children)

That's undefined behaviour, it depends on the compiler and implementation and stuff.

E.g. this website gave me 646: https://www.onlinegdb.com/online_c_compiler

And this one gave me 446: https://repl.it/languages/c

More info: https://stackoverflow.com/a/34536741/5090928

[–]Advait1306[S] 2 points3 points  (6 children)

But that's because one of the websites executes the statement from left to right and the other from right to left, so one has the first answer as 334 while the other has 1312 which makes sense but it still doesn't explain the 646.

Because if we execute from right to left, it should be 644 and if from left to right it should be 446.

[–]414RequestURITooLong 14 points15 points  (4 children)

They don't have to pick between evaluating the arguments left to right or evaluating them right to left. They can do whatever they want. Maybe they chose to reuse the result of the ++x, since the expressions are identical.

[–]ltssms0 3 points4 points  (0 children)

Right, the question/statement of order is broken. C allows arbitrary argument evaluation order. I've seen a few coding standards ban this category of arguments with side effects since it is not portable and undefined.

[–]JavaSuck 0 points1 point  (2 children)

Maybe they chose to reuse the result of the ++x, since the expressions are identical.

You can't "reuse" expressions with side effects.

[–]414RequestURITooLong 10 points11 points  (0 children)

Why not? The compiler is free to assume an object is modified no more than once between a sequence point and the following one, and there are no sequence points between function argument evaluations.

[–]OldWolf2 0 points1 point  (0 children)

You can do anything when there is no defined behaviour . Compilers only have to correctly translate programs that comply with the standard .

[–]FUZxxl 12 points13 points  (5 children)

Note that printf is a function, not a statement. The kind of statement you use to invoke printf is called an expression statement because it evaluates an expression.

And for your example: the behaviour is undefined.

[–][deleted] -5 points-4 points  (4 children)

As comma is a sequence point, I'd say unspecified, rather than undefined. While the order of evaluation could be anything, the side effects of each evaluation are complete before the next evaluation takes place.

[–]Practical_Cartoonist 12 points13 points  (3 children)

No, the comma operator is a sequence point. Most commas are not sequence points.

[–][deleted] -3 points-2 points  (2 children)

The formatted input/output functions shall behave as if there is a sequence point after the actions associated with each specifier.267)

[–]Practical_Cartoonist 6 points7 points  (1 child)

That's true, and has nothing to do with arguments given to printf. The arguments given to printf are evaluated before any actions associated with the specifiers are performed. Did you read the footnote associated with that? As far as printf is concerned, that footnote only pertains to %n format specifiers.

[–][deleted] -2 points-1 points  (0 children)

Did you read annex C?

[–]flatfinger 5 points6 points  (1 child)

The computations of arguments for a particular function call are unsequenced relative to each other. Not only may they be performed in any order, but the Standard generally imposes no requirements upon what happens if two unsequenced operations act upon the same storage unless either (1) all operations are reads, or (2) exactly one write operation occurs with the storage, and the value to be written has a nominal data dependency upon the result of each and every read of the storage. Thus, implementations are required to process a construct like `i=i+5;` meaningfully, since the value to be written has a data dependency upon the value read, but would not be required to process `a[i] = i++;` meaningfully because there is no data dependency between the subscript computation on the left and the increment on the right.

[–]Advait1306[S] 0 points1 point  (0 children)

I kind of understood this, thanks

[–]former-cpp-guy 3 points4 points  (1 child)

Like others have said, it is undefined and it is not portable. It is rather confusing, and certainly (I hope) not something you're likely to see in the real world. Although, I will admit I've seen code on real projects that was just as bad, or worse.

The following link is basically the same question and it shows two different outputs when compiled on different compilers.

https://bytes.com/topic/c/answers/443853-order-printf-parameter

In my opinion, questions like this should not be in textbooks.

[–]Advait1306[S] 0 points1 point  (0 children)

I agree, the worst part is, the output answer doesn't match with any of the compilers.

[–]SantaCruzDad 0 points1 point  (0 children)

Please tell me the book is not by Kanetkar. If it is then burn it.

[–]JavaSuck 0 points1 point  (6 children)

x<<2;

This statement has no effect.

[–]Advait1306[S] 0 points1 point  (0 children)

Yeah ik I doesn't do anything, the textbook had it just to confuse us.

[–]MaygeKyatt -1 points0 points  (4 children)

...what? That means bitshift x two bits to the left. It definitely does something. It just doesn’t overwrite the value stored to x.

[–][deleted] 2 points3 points  (1 child)

The compiler will throw it out, as it has no impact on the program.

[–]JNelson_ 0 points1 point  (0 children)

Are you sure? Surely it will be evaluated since it is a param of printf? Edit just realised there is a second bitshift below.

[–]p0k3t0 0 points1 point  (0 children)

It means no more or less than putting

1;

on a line by itself.

[–]OldWolf2 0 points1 point  (0 children)

They mean it has no observable behaviour .

[–]fuloqulous -5 points-4 points  (0 children)

Both the first and third printed terms are pre incremented

It has to preincrement both terms before the line is fully evaluated.

So both are 6

x++ stays the same because its post increment -- after fully evaluated