Thread: About precedence of && and ||

  1. #1
    Registered User
    Join Date
    May 2010
    Posts
    74

    About precedence of && and ||

    Hi, while I was helping in some programming exercises, there was this problem:
    Code:
    int i = 1, j = 1, k = 1;
    
    printf("%d ", ++i || ++j && ++k);
    printf("i:%d j:%d k:%d", i, j, k);
    I checked the precedence table of c operators, and saw that && has higher precedence than ||, so I guessed that the output for the variables would be: i:2 j:1 k:2 (j would be short-circuited).

    But when we tested it, the output was: i:2 j:1 k:1.
    Basically the || was evaluated first, and I didn't understand why.

    What's going on?

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    The precedence is telling you that you've got this

    ++i || ( ++j && ++k )

    and not this

    ( ++i || ++j ) && ++k
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    May 2010
    Posts
    74
    I still don't get it, because the || is been evaluated first. Doesn't having higher precedence means that it is evaluated first? This way the && isn't even considered.

  4. #4
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by noobiept View Post
    I still don't get it, because the || is been evaluated first. Doesn't having higher precedence means that it is evaluated first? This way the && isn't even considered.
    First the double || and && are for use in conditionals, not math. For example:

    if ((x > 6) || (y < 7))

    If you are doing math you use the single versions not the doubles.

    For order or precidence the general rule is:
    Deepest brackets first, working out.
    Once at top level, left to right.

    Try your code again using:
    Code:
    printf("%d ", ++i | ++j & ++k);
    printf("i:%d j:%d k:%d", i, j, k);
    If you want the AND to run first put brackets like this:
    Code:
    printf("%d ", ++i | (++j & ++k));
    printf("i:%d j:%d k:%d", i, j, k);
    Does that help?

  5. #5
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Quote Originally Posted by noobiept View Post
    I still don't get it, because the || is been evaluated first. Doesn't having higher precedence means that it is evaluated first? This way the && isn't even considered.
    Operator precedence is a different concept from order of evaluation. The two are very different things. One is how to build the syntax tree, the other is how to evaluate it.

    Operator precedence says that our syntax tree for this is the left one of these two:
    Code:
        ||                &&   
      /    \            /    \ 
    ++i    &&         ||    ++k
          /  \       /  \      
         ++j ++k    ++i ++j
    But it says nothing about the order the parts of the tree are evaluated.

    The order of evaulation in this case says to go from left to right, but short circuit evalution says to skip the right hand side when the left of an || is true or the left of an && is false. So we do ++i and then the || at the top of our tree is satisfied and we therefore stop.
    Last edited by iMalc; 09-10-2010 at 02:46 PM.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  6. #6
    Registered User
    Join Date
    May 2010
    Posts
    74
    Ok, I was assuming that operator precedence would determine the order of evaluation. Didn't know it was something different.
    Guess I learned something today

    Just a last question, how do we know that the expression is evaluated from left to right? Is it compiler dependent or something?

  7. #7
    Woof, woof! zacs7's Avatar
    Join Date
    Mar 2007
    Location
    Australia
    Posts
    3,459
    Quote Originally Posted by CommonTater View Post
    First the double || and && are for use in conditionals, not math. For example:

    if ((x > 6) || (y < 7))

    If you are doing math you use the single versions not the doubles.

    For order or precidence the general rule is:
    Deepest brackets first, working out.
    Once at top level, left to right.

    Try your code again using:
    Code:
    printf("%d ", ++i | ++j & ++k);
    printf("i:%d j:%d k:%d", i, j, k);
    If you want the AND to run first put brackets like this:
    Code:
    printf("%d ", ++i | (++j & ++k));
    printf("i:%d j:%d k:%d", i, j, k);
    Does that help?
    | and & are just as mathematical as && and ||. I don't see what bitwise operators have to do with anything the OP was asking.

    Quote Originally Posted by noobiept
    Just a last question, how do we know that the expression is evaluated from left to right? Is it compiler dependent or something?
    It's defined by the standard. A quick google for "C operator table" will probably give you good results (from a reliable source, preferably the standard :-)).
    Last edited by zacs7; 09-10-2010 at 05:10 PM.

  8. #8
    Registered User
    Join Date
    May 2010
    Posts
    74
    I was referring to the order of evaluation, and not the operator precedence (or maybe I'm confusing myself?)

  9. #9
    Registered User
    Join Date
    May 2010
    Location
    Naypyidaw
    Posts
    1,314
    ++i || ++j && ++k
    ++i || (++j && ++k) // && and higher precedence
    2 || (++j && ++k) // left to right evaluated
    2 || whatever_exp // is always true , now short-circuit! whatever_exp is not evaluated!

    So j and k are never incremented. Got it?

  10. #10
    Registered User
    Join Date
    Jul 2010
    Location
    Oklahoma
    Posts
    107
    noobiept,

    According to Wang, Paul S. An Introduction to ANSI C on UNIX Boston: PWS 1993. ISBN: 0-534-14232-X, operator precedence is given on page 397 as, and the associativity is (always) left to right unless otherwise marked:

    Code:
    Operator				Associativity
    () [] -> .
    !~ ++ -- + - * & (type) sizeof		<----
    * / %
    + -
    << >>
    < <= > >=
    == !=
    &
    ^
    |
    &&
    ||
    ?:					<----
    = += -= *= /= %= ^= |= <<= >>=		<----
    ,
    These are also listed on the Wikipedia: Operators in C and C++ - Wikipedia, the free encyclopedia.

    Best Regards,

    New Ink -- Henry

  11. #11
    Registered User
    Join Date
    May 2010
    Posts
    74
    I think you didn't understand what I was saying, but either way I search a bit and read about it.
    thanks for the answers!

  12. #12
    Woof, woof! zacs7's Avatar
    Join Date
    Mar 2007
    Location
    Australia
    Posts
    3,459
    Quote Originally Posted by noobiept
    I was referring to the order of evaluation, and not the operator precedence (or maybe I'm confusing myself?)
    Just think about it... order of evaluation is very important, especially if the given operators have the same precedence.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Compiling C in Visual Studio 2005
    By emanresu in forum C Programming
    Replies: 3
    Last Post: 11-16-2009, 04:25 AM
  2. Personal Program that is making me go wtf?
    By Submeg in forum C Programming
    Replies: 20
    Last Post: 06-27-2006, 12:13 AM
  3. process killer on a loop
    By Anddos in forum Windows Programming
    Replies: 8
    Last Post: 01-11-2006, 01:50 AM
  4. Massive Function Problem
    By Marc Sharp in forum C Programming
    Replies: 10
    Last Post: 11-19-2003, 08:49 PM
  5. Tic Tac Toe Help
    By aresashura in forum C++ Programming
    Replies: 1
    Last Post: 11-21-2001, 12:52 PM