In previous versions of the standard (C++03) the order of evaluation of parameters to a function call was unspecified.
Has this been changed in subsequent version of the standard (C++11 or C++14)?
i.e. Can we rely on a specific ordering (left to right) or not.
No this has not changed but there is a very recent proposal to change this: N4228: Refining Expression Evaluation Order for
Idiomatic C++, this was part of the Pre-Urbana mailing that came out this October The introduction says (emphasis mine going forward):
Expression evaluation order is a recurring discussion topic in the
C++ community. In a nutshell, given an expression such as f(a, b, c),
the order in which the sub-expressions f , a , b , c are evaluated
is left unspecified by the standard. If any two of these
sub-expressions happen to modify the same object without intervening
sequence points, the behavior of the program is undefined. For
instance, the expression f(i++, i) where i is an integer variable
leads to undefined behavior
it proposes:
We propose to revise C++ evaluation rules to support decades-old
idiomatic constructs and programming practices. A simple solution
would be to require that every expression has a well-defined
evaluation order. That suggestion has traditionally met resistance for
various reasons. Rather, this proposes suggests a more targeted fix
Postfix expressions are evaluated from left to right. This includes
functions calls and member section expressions.
Assignment expressions are evaluated from right to left. This includes compound assignments.
Operands to shift operators are evaluated from left to right
Update
Herb Sutter recently put out a poll on order of evaluation looking for some feedback from the community on what result we would expect from the following code:
std::vector<int> v = { 0, 0 };
int i = 0;
v[i++] = i++;
std::cout << v[0] << v[1] << endl;
This would seem to indicate the committee is looking at the topic of order of evaluation seriously but as we can see from the discussion this is controversial.
No it is still unspecified in C++11. This is so your compilers can do micro optimizations that would improve the quality of the code, and is varied from compiler to compiler. Try printf with increment operations on different compilers.
functions like int i = foo(3) + bar(0); has undefined behaviors, no function is guaranteed to operate first.
Related
This question already has answers here:
Why are these constructs using pre and post-increment undefined behavior?
(14 answers)
Closed 3 years ago.
Just to see how much I understood how the ++c/c++ operator works, I tried to run these C programs:
int c = 5;
c = c - c++;
printf("%d\n", c);
prints 1, I guess the logic is that the ++ is applied after the line of code where it's used, so c becomes = c - c which is 0, and on the "next line" it's increased by one. But it seems strange to me, I'd like to know more in detail what should happen with regards to the operators priority.
Now on to this:
int c = 5;
c = c - ++c;
printf("%d\n", c);
this one prints 0, and I can't really understand why. If right hand values are parsed from left to right, I guess it would read c which is 5, then ++c which is 6 as it should be applied immediately. Or does it calculate the ++c before the whole right hand value calculation, so that it's actually doing 6 - 6 because the increment also involves the first calling of c?
For C++ (all versions, explanation applies to C++11 and later):
Both have undefined behavior, meaning that not only is the value that it will return unspecified, but that it causes your whole program to behave in an undefined manner.
The reason for this is that evaluation order inside an expression is only specified for certain cases. The order in which expressions are evaluated does not follow the order in the source code and is not related to operator precedence or associativity. In most cases the compiler can freely choose in which order it will evaluate expressions, following some general rules (e.g. the evaluation of an operator is sequenced after the value computation of its operands, etc.) and some specific ones (e.g. &&'s and ||'s left-hand operands are always sequenced before their right-hand operands).
In particular the order in which the operands of - are evaluated is unspecified. It is said that the two operands are unsequenced relative to one another.
This in itself means that we won't know whether c on the left-hand side of c - [...] will evaluate to the value of c before or after the increment.
There is however an even stricter rule forbidding the use of a value computation from a scalar object (here c) in a manner unsequenced relative to a side effect on the same scalar object. In your case both ++c and c++ cause side effects on c, but they are unsequenced with the use of the value on the left hand side of c - [...]. Not following this rule causes undefined behavior.
Therefore your compiler is allowed to output whatever it wants and you should avoid writing code like that.
For a detailed list of all the evaluation order rules of C++, see cppreference.com. Note that they changed somewhat with the different C++ versions, making more and more previously undefined or unspecified behavior defined. None of these changes apply to your particular case though.
c = c - c++;
In C, this is a very bad idea(a). You are not permitted to modify and modify/use the same object without an intervening sequence point, and that subtraction operator is not a sequence point.
The things that are sequence points can be found in Annex C of the ISO standard.
(a) Technically, the behaviour of each operation (the evaluation of c1 and c++, and the assignment to c) is well defined but the sequencing is either unsequenced or indeterminate. In the former case, actions from each part can interleave while, in the latter, they do not interleave but you don't know in which order the two parts will be done.
However, the standard C11 6.5/2 also makes it clear that a sequencing issue using the same variable is undefined behaviour:
If a side effect on a scalar object is unsequenced relative to either a different side effect on the same scalar object or a value computation using the value of the same scalar object, the behavior is undefined. If there are multiple allowable orderings of the subexpressions of an expression, the behavior is undefined if such an unsequenced side effect occurs in any of the orderings.
Bottom line, it's not something you should be doing.
In another answer it was stated that prior to C++11, where i is an int, then use of the expression:
*&++i
caused undefined behaviour. Is this true?
On the other answer there was a little discussion in comments but it seems unconvincing.
It makes little sense to ask whether *&++i in itself has UB. The deferencing doesn't necessarily access the stored value (prior or new) of i, as you can see by using this as an initializer expression for a reference. Only if an rvalue conversion is involved (usage in such context) is there any question to discuss at all. And then, since we can use the value of ++i, we can use the value of *&++i with exactly the same caveats as for ++i.
The original question concerned essentially i = ++i, which is the same as i = *&++i. That was undefined behavior in C++03, due to i being modified twice between sequence points, and is well-defined in C++11, due to the side-effects of the assignment operator being sequenced after the value computations of the left and right hand sides.
It is perhaps relevant to note that the non-normative examples in the C++98 and C++03 standards, were incorrect, describing some cases of formally Undefined Behavior as merely unspecified behavior. Thus, the intent has not been entirely clear, all the way back. A good rule of thumb is to simply not rely on such obscure corner cases of the language, to avoid them: one should not need to be a language lawyer in order to make sense of the code…
I think the question only makes sense if we deal with the expression:
i = *&++i;
The relevant quote in the C++03 standard would be [expr]/4:
Except where noted, the order of evaluation of operands of individual operators and subexpressions of individual
expressions, and the order in which side effects take place, is unspecified. Between the previous
and next sequence point a scalar object shall have its stored value modified at most once by the evaluation
of an expression. Furthermore, the prior value shall be accessed only to determine the value to be stored.
The requirements of this paragraph shall be met for each allowable ordering of the subexpressions of a full
expression; otherwise the behavior is undefined.
i = ++i + 1; // the behavior is unspecified
We can just compare the sequencing of i = *&++i vs i = ++i + 1 to determine that the same rule causes both to be unspecified. They are both statements of the form:
i = f(++i);
For any function f, the reading of i on the left-hand side and the side-effect of the ++i on the right-hand side are not sequenced relative with each other. Hence, undefined behavior.
In the expression a + b, is a guaranteed to be evaluated before b, or is the order of evaluation unspecified? I think it is the latter, but I struggle to find a definite answer in the standard.
Since I don't know whether C handles this different from C++, or if evaluation order rules were simplified in C++11, I'm gonna tag the question as all three.
In C++, for user-defined types a + b is a function call, and the standard says:
§5.2.2.8 - [...] The order of evaluation of function arguments is unspecified. [...]
For normal operators, the standard says:
§5.4 - Except where noted, the order of evaluation of operands of individual operators and subexpressions of individual expressions, and the order in which side effects take place, is unspecified. [...]
These haven't been changed for C++11. However, the wording changes in the second one to say that the order is "unsequenced" rather than unspecified, but it is essentially the same.
I don't have a copy of the C standard, but I imagine that it is the same there as well.
It is Unspecified.
Reference - C++03 Standard:
Section 5: Expressions, Para 4:
except where noted [e.g. special rules for && and ||], the order of evaluation of operands of individual operators and subexpressions of individual expressions, and the order in which side effects take place, is Unspecified.
C++0x FDIS section 1.9 "Program Execution" §15 is similar to the corresponding paragraph in C++03, just reworded to accommodate the conceptual change from "sequence points" to "being sequenced":
Except where noted, evaluations of operands of individual operators and of subexpressions of individual expressions are unsequenced.
It is unspecified. C and C++ follow the same logic in selecting sequence points:
https://en.wikipedia.org/wiki/Sequence_point
For C: "Order of operations is not defined by the language. The compiler is free to evaluate such expressions in any order, if the compiler can guarantee a consistent result." [...] "Only the sequential-evaluation (,), logical-AND (&&), logical-OR (||), conditional-expression (? :), and function-call operators constitute sequence points and therefore guarantee a particular order of evaluation for their operands."
Source: http://msdn.microsoft.com/en-us/library/2bxt6kc4.aspx
The way this is organized in that article, it seems to indicate this applies to C++ too, which is confirmed by the answer to this question: Operator Precedence vs Order of Evaluation.
According to the current C standard, C11, it also specifies that the order of evaluation of subexpressions (a and b in this case) is indeterminate. In fact, this order doesn't even have to be the same if the same expression is evaluated multiple times.
From section 6.5:
The grouping of operators and operands is indicated by the
syntax.85) Except as specified later, side effects and
value computations of subexpressions are unsequenced.86)
86) In an expression that is evaluated more than once during the
execution of a program, unsequenced and indeterminately sequenced
evaluations of its subexpressions need not be performed
consistently in different evaluations.
What will be printed as the result of the operation below:
x=5;
printf("%d,%d,%d\n",x,x<<2,x>>2);
Answer: 5,20,1
I thought order is undefined yet I found above as interview question on many sites.
From the C++ standard:
The order of evaluation of arguments is unspecified. All side effects of argument expression evaluations take effect before the function is entered. The order of evaluation of the postfix expression and the argument expression list is unspecified.
However, your example would only have undefined behavior if the arguments were x>>=2 and x<<=2, such that x were being modified.
Bit shift operators don't modify the value of the variable... so order doesn't matter.
The order of evaluation is unspecified, but it doesn't matter because you're not modifying x at all.
So the program is well-defined, and the answer is as given.
The following would have undefined semantics:
printf("%d,%d,%d\n", x, x <<= 2, x >>= 2);
I found the answer in c++ standards.
Paragraph 5.2.2.8:
The order of evaluation of arguments is unspecified. All side effects
of argument expression evaluations take effect before the function is
entered. The order of evaluation of the postfix expression and the
argument expression list is unspecified.
In other words, It depends on compiler only.
The order of evaluation is undefined in the Official C Specification.
However, as a matter of practicality, parameters are usually evaluated right-to-left.
In your problem, the bit-shift operator doesn't change the value of X, so the order of evaluation is not important. You'd get 5,20,1, whether evaluated left-to-right, right-to-left, or middle-first.
In C, parameters are pushed on to the stack in a right-to-left order, so that the 1st param (in this case, the char* "%d,%d,%d") is at the top of the stack. Parameters are usually (but not always) evaluated in the same order they are pushed.
A problem that better illustrates what you're talking about is:
int i=1;
printf("%d, %d, %d", i++, i++, i++);
The official answer is "undefined".
The practical answer, (in the several compilers/platforms I've tried), is "3, 2, 1".
I have started studying about C++0x. I came across the follow expression somewhere:
int l = 1, m=2;
++l *= m;
I have no idea whether the second expression has well defined behavior or not. So I am asking it here.
Isn't it UB? I am just eager to know.
The expression is well defined in C++0x. A very Standardese quoting FAQ is given by Prasoon here.
I'm not convinced that such a high ratio of (literal Standards quotes : explanatory text) is preferable, so I'm giving an additional small explanation: Remember that ++L is equivalent to L += 1, and that the value computation of that expression is sequenced after the increment of L. And in a *= b, value computation of expression a is sequenced before assignment of the multiplication result into a.
What side effects do you have?
Increment
Assignment of the multiplication result
Both side-effects are transitively sequenced by the above two sequenced after and sequenced before.
In the code above, prefix ++ has precedence over *=, and so gets executed first. The result is that l equals 4.
UPDATE: It is indeed undefined behavior. My assumption that precedence ruled was false.
The reason is that l is both an lvalue and rvalue in *=, and also in ++. These two operations are not sequenced. Hence l is written (and read) twice "without a sequence point" (old standard wording), and behavior is undefined.
As a sidenote, I presume your question stems from changes regarding sequence points in C++0x. C++0x has changed wording regarding "sequence points" to "sequenced before", to make the standard clearer. To my knowledge, this does not change the behavior of C++.
UPDATE 2: It turns out there actually is a well defined sequencing as per sections 5.17(1), 5.17(7) and 5.3.2(1) of the N3126 draft for C++0x. #Johannes Schaub's answer is correct, and documents the sequencing of the statement. Credit should of course go to his answer.