This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

C Problem?

unsigned char x=1;
x=(x++)<<3;

Using uVision 6.12
Gives answer of 8
It shifts binary 1 left and doesn't increment.
(even when optimization set to level 0)

Using Micorsoft C++ 6.0
Gives answer of 9
It shifts binary 1 left then increments.


I was a little confused with both answers because I was thought that
the increment would happen first because of the ( ) around x++ then
shift left three giving 16 but that's not the case.

This gives me 16 in both Keil and MS.
x=(++x)<<3; works it gives 16


Parents
  • Keil does have some problems with the pre- and post- increment/decrement operators when used within a more complicated expression.

    However, the value of the expression "x++" is x; the increment is not done until after the expression is evaluated - hence post increment!

    So

    (x++)<<3
    is equivalent to
    (x)<<3; x += 1
    and it seems that MSVC has the "right" answer.

    This kind of thing is often quoted to show the problems of macros!


Reply
  • Keil does have some problems with the pre- and post- increment/decrement operators when used within a more complicated expression.

    However, the value of the expression "x++" is x; the increment is not done until after the expression is evaluated - hence post increment!

    So

    (x++)<<3
    is equivalent to
    (x)<<3; x += 1
    and it seems that MSVC has the "right" answer.

    This kind of thing is often quoted to show the problems of macros!


Children
  • Since this equation produces undefined behavior, there is no right answer IMHO. See:

    http://www.eskimo.com/~scs/C-faq/q3.3.html


    I suggest:
    x = x + 1 << 3;
    and remember that + happens before <<.

    :-)

    - Mark

  • To Keil Discussion Forum site:

    Add the following suggestion to your "Tips for Posting Measages".

    If you type an URL like

    <pre>TheUrl</pre>

    then add a space before the </pre>.

    If you don't, one can not follow the hyperlink (using IE5.5) by clicking on it.

  • Actually, there is no need to use the &ltpre&gt and &lt/pre&gt tags for URLs at all - the forum automatically makes URLs clickable (as it says in the Tips).

    It seems that it's this automatic conversion to a link which has gone wrong - it's caught the closing &lt/pre&gt tag inside the closing &lt/a&gt link tag!
    So yes, a space (or newline?) before the &lt/pre&gt would probably have fixed it.

  • Sorry about that, I didn't mean to use the pre tag at all.

    - Mark

  • >Keil does have some problems with the pre- and
    >post- increment/decrement operators when used
    >within a more complicated expression

    Which problems your take in mind ?



    >(x++)<<3
    >is equivalent to

    >(x)<<3; x += 1
    >and it seems that MSVC has the "right" >answer.


    This is not exactly the same as original qiestion:

    unsigned char x = 1;
    x=(x++) << 3;
    

    is equivalent to

    unsigned char x = 1;
    unsigned char tmp;
    
    tmp = x;          // get old value of 'x'
    x   = x + 1;      // x++
    x   = (tmp << 3); // Assign('=') have lowest priority
    
    

    So, right answer is 'x==8' after all.



  • Please see

    http://www.eskimo.com/~scs/C-faq/q3.3.html

    x = (x++) << 3;
    not only are the parens useless since ++ is much higher precedence than << but the resultant value assigned to x is up to the implementation (compiler) you are using. This sort of equation should be written as
    x = x + 1 << 3;
    Let the compiler figure out that +1 means INC.

    Regards,

    - Mark

  • Mark,
    thanks for good point:
    http://www.eskimo.com/~scs/C-faq/q3.3.html

    http://www.eskimo.com/~scs/C-faq/top.html

    It is a good place to understand why I intuitively avoid some
    ambiguous C-constructions :)

    On the other side, this is a 'style' quiestion.
    For example, in your case I always write as

    x = (x + 1) << 3;
    
    despite that "no need" parens,
    just to produce evident readability.


    But if we return to original question,
    unsigned char x = 1;
    x = (x++) << 3;
    
    I think that in this case Keil-implementation "more suitable" :),
    because MSVC result '9'
    (accordingly author's original message)
    can be explained only if suppose that 'x++' evaluated after assigning '8' to x.

    As I remember, '=' operation in C:
      LVALUE = EXPRESSION
    
    calculated from right to left.

    I think, this means that
    at first
    EXPRESSION should be COMPLETELY evaluated (with all nested operations, EVEN side-effect operations such as function calls),
    then
    result of expression saved to place
    pointed by LVALUE.


    This is just my common-sense opinion :)

  • unsigned char x = 1;
    x = (x++) << 3;
    "MSVC result '9' ... can be explained only if suppose that 'x++' evaluated after assigning '8' to x."

    Which is what I'd expect from a post increment:

    "x++" means "take the value of x and then, when you've done with it, increment x by one"

    In this case, "when you've done with it" means, "when you've shifted it"

    However, I agree with the consensus that this is ambiguous and best avoided!