Jump to content
  • Advertisement
Sign in to follow this  
baixiangzhlt

A tricky C problem

This topic is 4137 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

The question is : int a=10; a+=a-=a*=a; Put these statements into a test driver and execute that program I find that the result is 0.How can it be?Can you please tell me what happens?I evaluate the result to be 100,since +=,-=and*= have the same priority.Thank you.

Share this post


Link to post
Share on other sites
Advertisement
The result is undefined - you can't do more than one assignment per sequence point. In this case it's probably doing

a+=a (a=20)
a-=a (a=0)
a*=a (a=0)

but you can't rely on this - the compiler could legitimately do whatever it wanted

Share this post


Link to post
Share on other sites
Quote:
Original post by cshowe
The result is undefined - you can't do more than one assignment per sequence point.


No, you forgot to do your homework, multiple assignments are very well possible; operator precedence, esp. the assignment operators are to be evaluated "from-right-to left" (contrary to the 'normal' left-to-right order).

Next time please prefix your post with "I think" or "In my humble opinion" rather than saying "It is".


a=10;
a+=a-=a*=a;


is the same as:


a+=(a-=(a*=a));


let's partition that:


a=10;
a*=a; //> a is now 100
a-=a; //> == "100-100", so after that op a is 0
a+=a; //> == "0+0", easy, not?



Hope that helps you, baixiangzhlt :)


edit: btw, what I find comfortable from time to time is a construct like this:


int res;

if( 0 != (res=foo()) ){
...
}else{
return res;
}

//> or even
if( res=bar() ){
...
}else{
return res;
}

//> this one is very useful:
x[0] = x[1] = x[2] = 0; //> saves a lot of lines and helps the compiler for SIMD

Share this post


Link to post
Share on other sites
Quote:
Original post by greenhybrid
Quote:
Original post by cshowe
The result is undefined - you can't do more than one assignment per sequence point.


No, you forgot to do your homework, multiple assignments are very well possible;


You are probably right, but for the wrong reasons.

Multiple assignments (or, more generally, modifications) per sequence point are generally evaluated in an unspecified order which is independent of operator precedence. Consider:

int a = 1;
return (a += 2) + (a *= 2);


The order of precedence is fully specified through means of parentheses, yet we do not know whether this code returns 6 or 9.

Chained assignments (as opposed to multiple assignemnts), do not have this problem. I do not know for chained modifications. The standard probably specifies how the += operators act, but I don't have it with me right now. The risk is having:
a = 1;
a += (a *= 2);

// Equivalent to:
a = (a + (a = (a * 2)));


Evaluated as:
a = (1 + (a = (1*2)); // --> a = 3


EDIT: apparently, it's undefined even for chained modifications, if you modify the same variable twice.

[Edited by - ToohrVyk on May 25, 2007 7:15:23 AM]

Share this post


Link to post
Share on other sites
Quote:
Original post by baixiangzhlt
The question is :
int a=10;
a+=a-=a*=a;
Put these statements into a test driver and execute that program I find that the result is 0.How can it be?Can you please tell me what happens?I evaluate the result to be 100,since +=,-=and*= have the same priority.Thank you.


This one seems easy enough; the compiler looks at the code as sub sections.

a + (a - (a * a))
a - (a * a)
a * a;

so looking at this, a*a = 100 (there you are correct); however a (as it now exists) would be 100 and thus would be 100 - 100 = 0. Then you take the last portion of 0 + 0 = 0 where the actual result shows.

-Root

Share this post


Link to post
Share on other sites
Quote:
Original post by ToohrVyk
Quote:
Original post by greenhybrid
Quote:
Original post by cshowe
The result is undefined - you can't do more than one assignment per sequence point.


No, you forgot to do your homework, multiple assignments are very well possible;


...

Multiple assignments (or, more generally, modifications) per sequence point are generally evaluated in an unspecified order which is independent of operator precedence. Consider:

int a = 1;
return (a += 2) + (a *= 2);


The order of precedence is fully specified through means of parentheses, yet we do not know whether this code returns 6 or 9.

...


The compiler is very well defined by the means of operator precedence, that is operator priority as well as whether the sub-statements are evaluated left-to-right or right-to-left.

Since add's go left-to-right, at first the left term (a+=2) is evaluated, and then the term on the right, (a*=2).

1) Let a=1
2) Evaluate left term, evaluate expression in brackets, have a = a+2 = 3 now
3) Evaluate right term, evaluate expression in brackets, with a=3, we have a = a*2 = 6 now


Share this post


Link to post
Share on other sites
Quote:
Original post by greenhybrid
The compiler is very well defined by the means of operator precedence, that is operator priority as well as whether the sub-statements are evaluated left-to-right or right-to-left.


Operator precedence (or associativity) has nothing to do with evaluation order—precedence only dictates how the abstract syntax should be built, it does not impose any sense of priority or timing over the various branches of that syntax tree at evaluation time.

In particular, in an expression such as a + b, a may be evaluated before or after b depending on compile-time and even runtime considerations—the standard is pretty clear on allowing compiler writers this freedom. See this FAQ entry, for instance.

Quote:
Since add's go left-to-right, at first the left term (a+=2) is evaluated, and then the term on the right, (a*=2).


I'd be curious to know where you got this information (the "add's go left-to-right" part) from in the first place. Are you sure you're not confusing this with associativity? Because adds are, indeed, left-to-right associative, but associativity has no bearing here (it only plays a role when you're adding more than three subexpressions together).

Share this post


Link to post
Share on other sites
If you take out the a-= portion of the equation, thus leaving you with

a+=a*=a;

You'll notice that the answer becomes 200. Once again proving that a+= is probably done first however the compiler must find out what a*=a is before it can add it to itself.

Share this post


Link to post
Share on other sites
Quote:
If you take out the a-= portion of the equation, thus leaving you with

a+=a*=a;

You'll notice that the answer becomes 200. Once again proving that a+= is probably done first however the compiler must find out what a*=a is before it can add it to itself.


That doesn't "prove" anything, except perhaps the behaviour of one *particular* compiler version with a *particular* set of parameters.

The behaviour of compilers doesn't matter. What matters is what the *Standard* says.

It's very simple. *ANY* side effect in an expression ins *ONLY* guaranteed by the Standard to be completely executed at the next sequence point. The value of the expression (a+=4) *will* always be a+4, BUT the value of *a* is not necessarily updated before the next sequence point. Thus, writing to a and then reading its value without a delimiting sequence point (as happens in the OP's example), will trivially yield an implementation-defined value.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!