Increment and order of evaluation

  • Thread starter Asbjørn Sæbø
  • Start date
A

Asbjørn Sæbø

Lint gives me warning about a code fragment, saying that the result is
dependent upon order of evaluation. I fail to see that it can be so.
The code fragment below illustrates the situation:

-------------------
#define CONSTANT SOME_VALUE
uint16_t my_var = <another_value>;

my_var = ++my_var % CONSTANT;
----------------------

How can the order of evaluation affect the result of this calculation?
My reasoning is that the increment operator has higher presedence than
the modulo operator, and should therefore be applied to my_var before
the modulo operator is applied to my_var, regardless of which side of
the modulo operator is evaluated first. Therefore, order of
evaluation should not influence the result?

Am I correct? And if not, how and why?


Asbjørn Sæbø
 
P

pete

=?utf-8?b?QXNiasO4cm4gU8OmYsO4?= said:
Lint gives me warning about a code fragment, saying that the result is
dependent upon order of evaluation. I fail to see that it can be so.
The code fragment below illustrates the situation:

-------------------
#define CONSTANT SOME_VALUE
uint16_t my_var = <another_value>;

my_var = ++my_var % CONSTANT;
----------------------

How can the order of evaluation affect the result of this calculation?
My reasoning is that the increment operator has higher presedence than
the modulo operator, and should therefore be applied to my_var before
the modulo operator is applied to my_var, regardless of which side of
the modulo operator is evaluated first. Therefore, order of
evaluation should not influence the result?

Am I correct? And if not, how and why?

Your code has undefined behavior.
There's no sequence point in between your two assignment
operations on my_var.

Your code is a special case of
i = ++i;

The problem is that the increment assignment can take place
either prior to or after the other assignment operation.

While this seems like it could result
in only one of two different values,
the standard committee has decided that code like that is so crappy,
that the best thing to do
is to lump it in together with all other code
that tries to modify an object more than once
without an interveening sequence point,
and declare it as invoking "undefined behavior".

"Sequence points" is a major concept in C.
You can get a free copy of a public draft of the standard,
on the internet, that will explain sequence points.
Google for it.
After you read about sequence points,
you should probably want to discuss it again here.
 
E

Eric Sosman

Asbjørn Sæbø said:
Lint gives me warning about a code fragment, saying that the result is
dependent upon order of evaluation. I fail to see that it can be so.
The code fragment below illustrates the situation:

-------------------
#define CONSTANT SOME_VALUE
uint16_t my_var = <another_value>;

my_var = ++my_var % CONSTANT;
----------------------

How can the order of evaluation affect the result of this calculation?
My reasoning is that the increment operator has higher presedence than
the modulo operator, and should therefore be applied to my_var before
the modulo operator is applied to my_var, regardless of which side of
the modulo operator is evaluated first. Therefore, order of
evaluation should not influence the result?

Am I correct? And if not, how and why?

Your argument is right, but you're arguing about the
wrong thing. See Question 3.3 in the comp.lang.c Frequently
Asked Questions (FAQ) list at <http://www.c-faq.com/>.
 
A

Asbjørn Sæbø

pete said:
=?utf-8?b?QXNiasO4cm4gU8OmYsO4?= wrote:

Your code is a special case of
i = ++i;

The problem is that the increment assignment can take place
either prior to or after the other assignment operation.

OK, now I see it. Thanks to you and to Eric!

I'll have to read up on those sequence points.

Asbjørn
 
C

Chris Dollin

Asbjørn Sæbø said:
Lint gives me warning about a code fragment, saying that the result is
dependent upon order of evaluation. I fail to see that it can be so.
The code fragment below illustrates the situation:

-------------------
#define CONSTANT SOME_VALUE
uint16_t my_var = <another_value>;

my_var = ++my_var % CONSTANT;

The assignment may be done before or after the increment.
My reasoning is that the increment operator has higher presedence than
the modulo operator,

Yes, but that's got (almost) nothing to do with it. All precedence and
associativity do is define which operators have which operands [1].
They do /not/ define order-of-evaluation, which is provided by
operator-specific rules, the most commonly applicable rule being
"the order is unspecified"; order of evaluation is defined for
&&, ||, ?:, and the comma operator and that's about it [2].

So in your expression above

my_var = ++my_var % CONSTANT

the grouping is made explicit with

my_var = ((++my_var) % CONSTANT)

The expression `++E` means "compute the value `E+1`, return that as
the value of this expression, and store that value back into the
same location /by the next sequence point/". The time of the update
is loosely specified to allow implementors latitude for efficiency.
The store-back doesn't need to be immediate and it doesn't need to
be before the assignment. (In fact, multiple assignments to a location
with no intervening sequence point /specifically/ results in undefined
behaviour -- all bets are off, the compiler can do whatever it likes.)

Why you'd /want/ to write the code above is about as clear as its
meaning:

my_var = (my_var + 1) % CONSTANT;

is, at a guess, what you really wanted.

[1] And strictly, in C, the grammar that defines that doesn't /use/
precedence and associativity, it writes them out longhand; P&A
are just useful shorthands.

[2] Vague feeling that I've forgotten something that I'll remember
just as this post commits ...
 
W

Willem

Asbjørn wrote:
) OK, now I see it. Thanks to you and to Eric!
)
) I'll have to read up on those sequence points.

There's no reason to code it like that anyway. If you just want
the value of my_var plus one, you're better off writing ' (my_var + 1) '.


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 
B

Ben Bacarisse

Asbjørn Sæbø said:
Lint gives me warning about a code fragment, saying that the result is
dependent upon order of evaluation. I fail to see that it can be so.
The code fragment below illustrates the situation:

-------------------
#define CONSTANT SOME_VALUE
uint16_t my_var = <another_value>;

my_var = ++my_var % CONSTANT;

I think it would be better for lint to quote the reason why the above
has undefined behaviour -- an object is being modified twice between
one sequence point and the next. See:
http://c-faq.com/expr/ieqiplusplus.html
My reasoning is that the increment operator has higher presedence than
the modulo operator, and should therefore be applied to my_var before
the modulo operator is applied to my_var, regardless of which side of
the modulo operator is evaluated first. Therefore, order of
evaluation should not influence the result?

Operator precedence does not come into it. The requirement that every
object be modified only once between any two sequence points is
violated no matter what evaluation order is used.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,021
Latest member
AkilahJaim

Latest Threads

Top