b=c/d++;

In this, first d is incremented (because ++ has a higher priority than / or =), but c is divided by the unincremented value of d. Thus, the order of evaluation in this case is well-defined. But if we had written the above as:

b=(c)/(d++)

then which operand ( c or d++ ) is evaluated first is undefined. Isn't this what Dennis Ritchie meant in his book when he said :"C, like most languages, does not specify the order in which the operands of an operator are evaluated." ?. In the first case, the order in which the operands of '/' are evaluated can be gauged, but not in the second case. Is my understanding correct ?

Secondly, in the ubiquitous problem :

i=i++;

everyone (including Dennis Ritchie for a[i]=i++) seems to say that the behaviour of this is undefined and depends on the compiler. But isn't it true that, since the post-increment operator has a higher priority than = , i++ will be evaluated first, but the unincremented value of i will be passed to i and i should remain unchanged after all that ? (though it gets incremented in Turbo C). My question is that why is its behaviour said to be undefined when the rules of priority seem to define its behaviour perfectly.

Its bugging me a lot. I shall be highly grateful.

Recommended Answers

All 19 Replies

But isn't it true that, since the post-increment operator has a higher priority than = , i++ will be evaluated first, but the unincremented value of i will be passed to i

This is true

and i should remain unchanged after all that

while this is not.

An assignment operator has a side effect of modifying memory. A postincrement operator has a side effect of modifying memory. In a i=i++ case, both of them try to modify the same memory.

The standard says that the side effect must be completed at a so called sequence point. If a program has more than one side effect between sequence points, the order of their completion is undefined. I don't think it is a right place to discuss the rationale behind this decision. We just have to live with it.

An expression i = i++ does not have sequence points, therefore which modification happens the last is undefined.

PS: the sequence points are a semicolon; a function call; a comma operator, logical operators etc.
PPS: For example, && is a sequence point, hence i++ && i++ is well defined, whereas i++ & i++ is not. Isn't that funny?

b=c/d++ and b=(c)/(d++) are equivalent. The parentheses don't have any effect on how that expression will be evaluated.

>Is my understanding correct ?
You're a little confused, but mostly correct. It makes more sense if you use functions instead to illustrate the unspecified order of evaluation:

#include <stdio.h>

int fizz() { printf ( "fizz" ); return 1; }
int buzz() { printf ( "buzz" ); return 0; }

int main ( void )
{
  printf ( "%d\n", fizz() - buzz() );

  return 0;
}

It's unspecified whether this program prints "fizzbuzz1" or "buzzfizz1", because the order in which the operands to - are evaluated (ie. the order in which the functions are called).

>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.

However, even if you don't take that as an answer, I can still argue that there's an ambiguity you're not seeing. The side effect can take effect at any time before the next sequence point. So assuming you have i = i++; (where ; denotes a sequence point) here are two perfectly rational ways of evaluating the expression:

_temp = i;
++i;
i = _temp;
_temp = i;
i = _temp;
++i;

Thus a modifying side effect in an assignment statement (ignoring everything else) would at the very least need to be unspecified because there are at least two possible results for the expression.

b = c/d
b=(c)/(d++)

The parathesis does not change what happens. It still reads from left to right. The post-increment operator returns d and then increments d.

For example this is roughly what the post increment operator does:

temp = i;
i = i + 1;
return temp

This is true

while this is not.

An assignment operator has a side effect of modifying memory. A postincrement operator has a side effect of modifying memory. In a i=i++ case, both of them try to modify the same memory.

The standard says that the side effect must be completed at a so called sequence point. If a program has more than one side effect between sequence points, the order of their completion is undefined. I don't think it is a right place to discuss the rationale behind this decision. We just have to live with it.

An expression i = i++ does not have sequence points, therefore which modification happens the last is undefined.

PS: the sequence points are a semicolon; a function call; a comma operator, logical operators etc.
PPS: For example, && is a sequence point, hence i++ && i++ is well defined, whereas i++ & i++ is not. Isn't that funny?

Thanks!

f()+g()+h()

In this, is the order of evaluation undefined, or will the rules of associativity force f()+g() to be evaluated first ?[code=c]
f()+g()+h()

In this, is the order of evaluation undefined, or will the rules of associativity force f()+g() to be evaluated first ?

Thanks!

f()+g()+h()

In this, is the order of evaluation undefined, or will the rules of associativity force f()+g() to be evaluated first ?[code=c]
f()+g()+h()

In this, is the order of evaluation undefined, or will the rules of associativity force f()+g() to be evaluated first ?

b=c/d++ and b=(c)/(d++) are equivalent. The parentheses don't have any effect on how that expression will be evaluated.

>Is my understanding correct ?
You're a little confused, but mostly correct. It makes more sense if you use functions instead to illustrate the unspecified order of evaluation:

#include <stdio.h>

int fizz() { printf ( "fizz" ); return 1; }
int buzz() { printf ( "buzz" ); return 0; }

int main ( void )
{
  printf ( "%d\n", fizz() - buzz() );

  return 0;
}

It's unspecified whether this program prints "fizzbuzz1" or "buzzfizz1", because the order in which the operands to - are evaluated (ie. the order in which the functions are called).

>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.

However, even if you don't take that as an answer, I can still argue that there's an ambiguity you're not seeing. The side effect can take effect at any time before the next sequence point. So assuming you have i = i++; (where ; denotes a sequence point) here are two perfectly rational ways of evaluating the expression:

_temp = i;
++i;
i = _temp;
_temp = i;
i = _temp;
++i;

Thus a modifying side effect in an assignment statement (ignoring everything else) would at the very least need to be unspecified because there are at least two possible results for the expression.

Thanks:

Just one more thing!

f()+g()+h()

In this, is the order of evaluation undefined, or will the rules of associativity force f()+g() to be evaluated first ?[code=c]
f()+g()+h()

In this, is the order of evaluation undefined, or will the rules of associativity force f()+g() to be evaluated first ?

>In this, is the order of evaluation undefined, or will the
>rules of associativity force f()+g() to be evaluated first ?

I think you neglected to read my entire post, because I gave an example that answers your question. The order of evaluation is unspecified. You can't predict in which order the functions will be called. This is somewhat different from associativity, which is what I think is causing your confusion.

Also note that undefined and unspecified have significantly different meanings in C. Unspecified isn't necessarily a bad thing, but undefined is absolutely unacceptable.

In this, is the order of evaluation undefined, or will the
rules of associativity force f()+g() to be evaluated first ?

I think you neglected to read my entire post, because I gave an example that answers your question. The order of evaluation is unspecified. You can't predict in which order the functions will be called. This is somewhat different from associativity, which is what I think is causing your confusion.

Also note that undefined and unspecified have significantly different meanings in C. Unspecified isn't necessarily a bad thing, but undefined is absolutely unacceptable.

What I meant to say was in f()+g()+h()

due to the left-right associativity of the '+' operator, the leftmost '+' is evaluated first, i.e. f()+g() will be evaluated first, but whether f() or g() is evaluated is not known. Is this right.?

Please do reply.

>>due to the left-right associativity of the '+' operator, the leftmost '+' is evaluated first

Nope, its undefined. The '+' operator is not a sequence point. So its possible that in this code [ f()+g()+h() ] , anyone could evaluate first.

due to the left-right associativity of the '+' operator, the leftmost '+' is evaluated first

Nope, its undefined. The '+' operator is not a sequence point. So its possible that in this code (f()+g()+h()) , anyone could evaluate first.

Thanks! I got that.

One thing but, in statements as :

printf ("%d",c+c++);

if the initial value of c was 4, then the higher priority of ++ will cause c to be incremented, first of all, and the result will be 9

But, if either c or c++ can be evaluated first, when are the priority rules going to matter ? That's my biggest problem.

Plz do answer.

>One thing but, in statements as :
>printf ("%d",c+c++);
>if the initial value of c was 4, then the higher priority of ++ will
>cause c to be incremented, first of all, and the result will be 9

I think you need to look again at what the postfix increment operator does. Let's look at it from a less confusing example:

int a = 4;
int b = 4;

printf ( "%d\n", a + b++ );

a + b++ is equivalent to

a + b;
b += 1;

In no way would the increment take effect such that the result is 9, because the value of b from before the increment is used in the addition expression. The increment is effectively postponed until the next sequence point.

>But, if either c or c++ can be evaluated first, when are the priority rules going to matter ?
That should be obvious. The rules matter when you add more operators. Precedence says which operators are evaluated first. Associativity says which operators of the same precedence are evaluated first. If you don't have those rules in place, how are you going to be able to predict the result of the following expressions:

5 + 3 * 2 = 11 or 16?
8 - 3 - 2 = 3 or 7?

This is somewhat related; I like Chris Torek's explanations of many things:

Remember:

>>> Precedence and associativity are only for parsing. <<<

Do not equate `higher precedence' with `done first at runtime.'

>>> Evaluation order is effectively unspecified. <<<

Make sure your code does not depend on the actual order of evaluation.

>>> Side effects `finish' at sequence points. <<<

But I'd recommended reading this whole post.

Thanks for everything. Here is what I understood

c=a+b-c;

In this, since ';' is the only sequence point here, the order in whuch a,b and c are evaluated is udefined, but the left associativity of + and - ensures that the OPERATION a+b happens before any other operation. Right ?

Now in the following code :

a=++b/c*d;

By the same reasoning, the order of evaluation of b,c and d should be undefined. But in the case of b, evaluating means PERFORMING AN OPERATION (pre-increment) also. Since, an operation is involved, the priority rules will apply. So here, the evaluation of b has to occur before that of c or d as the pre-increment has a higher priority than either * or /.

So does it mean that in such cases, where pre and post increment operators are involved, the priority does decide at least some part of the order of evaluation of the expression (AS EVALUATING OPERANDS HERE INVOLVES AN OPERATION ON THEM, WHICH IS CONTROLLED BY PRIORITY AND ASSOCIATIVITY ?

In essence, it boils down to :

Is ++b treated as an operation on b or as an evaluation of b ?

Please Plz do reply

Anyone please !

commented: Stop bumping posts. We'll answer them when we get to them. -2
commented: You fail. -4

>In this, since ';' is the only sequence point here, the order in whuch
>a,b and c are evaluated is udefined, but the left associativity of +
>and - ensures that the OPERATION a+b happens before any other operation. Right ?

Correct.

>Is ++b treated as an operation on b or as an evaluation of b ?
++ is an operator and b is the operand to ++. It's a subexpression, the result of which is used in the nesting expression [i]result[/i] / c * d .

Thanks a lot!

This part of the question though was left :

In the following code :

a=++b/c*d;

since there is only one sequence point here also, the order of evaluation of b,c and d should be undefined. But in the case of b, evaluating means PERFORMING AN OPERATION (pre-increment) also. Since, an operation is involved, the priority rules will apply. So here, the evaluation of b has to occur before that of c or d as the pre-increment has a higher priority than either * or /.

So does it mean that in such cases, where pre and post increment operators are involved, the priority does decide at least some part of the order of evaluation of the expression (AS EVALUATING OPERANDS HERE INVOLVES AN OPERATION ON THEM, WHICH IS CONTROLLED BY PRIORITY AND ASSOCIATIVITY ?

>since there is only one sequence point here also, the
>order of evaluation of b,c and d should be undefined.

I've told you this before. Undefined and unspecified are two very different terms with a very important distinction. You're using undefined inappropriately. The order of evaluation is unspecified, not undefined.

>Since, an operation is involved, the priority rules will apply.
Obviously. It's no different from a + b * c. Precedence states that the expression will be parsed as (a + (b * c)) rather than ((a + b) * c). It seems you're having trouble applying these rules to unary operators, but it works the same way. The only confusing part is how side effects occur:

a = b++ / c * d;

In the above statement, b++ does indeed happen first due to the higher precedence of ++. But the side effect isn't completely applied until the sequence point (a semicolon).

Order of evaluation explained in great detail at the below link:

<<snip>>

Thanks a lot!

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.