This question already has answers here:
What you're looking for is in section 6.5 on Expressions, paragraph 3 of the
The grouping of operators and operands is indicated by the syntax.
Except as specified later, side effects and value computations of
subexpressions are unsequenced.
This means that the side effect of incrementing (or decrementing) via the
-- operators doesn't necessarily happen immediately when the operator is encountered. The only guarantee is that it happens before the next sequence point.
In the case of
i = i++;, there is no sequence point in the evaluation of the operands of
= nor in the evaluation of postfix
++. So an implementation is free to perform assigning the current value of
i to itself and the side effect of incrementing of
i in any order. So
i could potentially be either 2 or 3 in your example.
This goes back to paragraph 2:
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.
i = i++ attempts to update
i more than once without a sequence point, it invokes undefined behavior. The result could be 2 or 3, or something else might happen as a result of optimizations for example.
The reason that this is
not undefined: int p;
p = f1() + f2()
Is because a variable is not being updated more than once in a sequence point. It
could however be unspecified behavior if both
f2 update the same global variables, since the evaluation order is unspecified.
Operators Precedence in C, What is the best way to force your own operator precedence? foo has a side effect, so the compiler can't just throw out the call without changing the program's behavior, and removing the call deterministically is rather difficult. However, if one side of an && or || is a constant, it's easy to ignore.
The problem with using
i = i++
is that the order in which the address of
i is accessed to read and write is not specified. As a consequence, at the end of that line, the value of
i could be
When will it be
Evaluate the RHS -
Assign it to the LHS.
i is now
i is now
When will it be
Evaluate the RHS -
i is now
Assign the result of evaluating the RHS to the LHS.
i is now
Of course, if there is a race condition, we don't know what's going to happen.
Chapter 4 Answers, What is the precedence of arithmetic operators from highest to lowest? The C integer conversion rules define how C compilers handle conversions. These rules include integer promotions , integer conversion rank , and the usual arithmetic conversions . The intent of the rules is to ensure that the conversions result in the same numerical values and that these values minimize surprises in the rest of the computation.
But nowhere could I see the issue of operator precedence being addressed in this issue.
Operator precedence only affects how expressions are
parsed (which operands are grouped with which operators) - it has no effect on how expressions are evaluated. Operator precedence says that
a * b + c should be parsed as
(a * b) + c, but it
doesn't say that either
must be evaluated before
Now we do not know whether the (i++) in LHS or RHS of '*' operator is going to be evaluated first. But either way it is going produce the same result. So how is it undefined?
Because the side effect of the
++ operator does not have to be applied immediately after evaluation. Side effects may be deferred until the next sequence point, or they may applied before other operations, or sprinkled throughout. So if
i is 2, then
i++ * i++ may be evaluated as
2 * 2, or
2 * 3, or
3 * 2, or
2 * 4, or
4 * 4, or
something else entirely. Precedence of Logical Operators, When one of these operators is overloaded (clause 13) in a valid context, thus designating What is the relation between Undefined Behaviour and Sequence Points? This rule effectively constrains legal expressions to those in which the In C99(ISO/IEC 9899:TC3) which seems absent from this discussion thus far the The parentheses are needed because the * operator has less precedence then the ( ) one. In the case of using the subscript operator, the resulting expression wouldn't be actually valid after the declaration because the index used in it (the value inside [ and ] ) will always be 1 above the maximum allowed value for this object/function.
OPERATOR PRECEDENCE DOES
NOT RESOLVE UNDEFINED EXPRESSION ISSUES.
Sorry for shouting, but people ask about this
all the time. I'm afraid I have to say your research on this question must not have been very thorough, if you didn't see this aspect being discussed.
See for example
i = i++ tries to assign to object
i twice. It's therefore undefined. Period. Precedence doesn't save you.
The precedence of arithmetic operators is (from highest to lowest , This is not to be confused with left-to-right and right-to-left associativity of operators: the expression a() + b() + c() is parsed as (a() + b()) + c() If a is an object of user-defined type which overloads the operator, then again there are two cases. If the return type of overloaded operator function is built-in type, then again a[++i]=i invokes undefined-behavior or the result is unspecified. c++ - Undefined behavior and sequence points, Operator precedence and associativity work in Perl more or less like they do in mathematics. Operators borrowed from C keep the same precedence relationship with a variable twice in the same statement will lead to undefined behavior. One effect of these rules is that -bareword is equivalent to the string "-bareword" Start studying PSY201 Exam 4 C10 C11 C12. Learn vocabulary, terms, and more with flashcards, games, and other study tools. Order of evaluation - cppreference.com, The precedence and associativity of C operators affect the grouping and evaluation Where several operators appear together, they have equal precedence and are evaluated Order of operations is not defined by the language. Specific rule (more than one operator of the same type in the same line). Operator precedence is often associated with order of evaluation, however order of evaluation and operator precedence are actually undefined in C. Expressions may be evaluated in any order while
perlop, Operators in C have rules of precedence and associativity that determine how as if, in the innermost block containing the call, the following declaration had appeared: from the expression containing the called function, the behavior is undefined. Such a scenario may occur for an external function declared with conflicting >My question is that why is its behaviour said to be undefined >when the rules of priority seem to define its behaviour perfectly. There's another rule that states an object can't be modified more than once between sequence points, which is the determining factor in making this and similar expressions undefined.
i++ will be evaluated and value will be returned. The UB is arising not from this but from the fact you can't know
when the value of
i is going to be
updated as a result of this operation. @EugeneSh.: Why cannot we be sure about it? i++ update the value of i when called independently. Why not update when called in an expression? Because C is not working this way. The side effect of
i++ is guaranteed to be carried out only after a sequence point, but not guaranteed
not to be carried out before. In Java it will be like you describe (AFAIK) does
i get set to
i and then the side-effect
i++ takes place, or does the side-effect happen first only for
i to be set to the value of what
i was before the side-effect?
Please don't add extra questions after receiving two comprehensive answers. You said that the evaluation of operands of '=' has no sequence point. But isn't there an implicit sequence point in evaluation of operands of '=' ? The LHS of '=' operator is guaranteed to be an l-value. If we write say int a = f(), the operands are a and f(). Now isn't it guaranteed here that f() will be evaluated first? Can you cite an example where the LHS of the assignment operator could be evaluated first leading to UB? @TARS You're correct that the right hand side of an assignment must be evaluated before being assigned to the left side. However, the left side needs to be evaluated as well. For example if
a is an array, then
a[f()] is an lvalue. That needs to be evaluated before it can be assigned to. So in an expression like
a[f()] = g(); whether
g is run first is unspecified.
@TARS And that still doesn't touch on side effects such as those caused by
I wish to get one more point clear. Say we consider the example you gave here, a[f()] = g(). Let us say g() gets evaluated first and suppose g() modifies some global variable int a and finally it returns some other variable int c. Now we are guaranteed that all the body of the function will be done before it returns the final value. In general all the side effects will be updated before the value is returned. So with the same logic here why is it that the value is returned by i++ but the side effect of incrementing the value i may not be done? @TARS Calling a function creates a sequence point. Using
++ does not.
How can the expression give 2*4 or 4*4 ? In any case the value returned by the i++ on the right side of * will always be 2 if i = 2 right ? @TARS: No, there is no such guarantee. I didn't have time to run through research papers and I only looked in stack overflow for this question and I couldn't find any article which differentiates it. Also I did not expect the rules to change just because I asked about it. Just a process of learning is all.