Friday, May 18, 2012

Operator Precedence 101

#include <stdio.h>
 
int main() {
 
 
    int a = 1;
    int b = 0;
 
    // Following two statements returns the same output
    printf("\nhah %d", a != 0 & b != 0); // returns 1
    printf("\nhah %d", a != 0 && b != 0); // returns 1
 
    // Despite the common misconception that the statement 1 when written explicitly
    // is this...
    printf("\nmeh %d", (a != (0 & b)) != 0); // returns 0
    // ..., statement 1's AND(&) operator still retain the same operator precedence as its short-circuit cousin(&&)
 
 
    printf("\n");
 
    const int ALT_KEY = 2;
    int input = 1;
     
    // should return 0, it returns 0:
    printf("\nhah %d", (input & ALT_KEY) == ALT_KEY);
 
    // despite the expectation that this "should" return 0, this doesn't return 0:
    printf("\nmeh %d", input & ALT_KEY == ALT_KEY);
 
    // So it means, despite the introduction of short-circuit operator,
    // the non-short-circuit logical/bitwise operator (&,|) still retain their 
    // operator precedence.
    // Hence, the unparenthesized expression (input & ALT_KEY == ALT_KEY), when written explicitly is still evaluated as:
    printf("\nhah %d", input & (ALT_KEY == ALT_KEY) ); // returns 1
 
    // Similar with operator precedence of logical operator:
    printf("\nhah %d", input && ALT_KEY == ALT_KEY ); // returns 1
     
    // Logical operator when written explicitly
    printf("\nhah %d", input && (ALT_KEY == ALT_KEY) ); // returns 1
     
 
 
    printf("\n");
}


You might notice that I mentioned the phrase still retain two times. There was a time that there was no short-circuit operators, && and ||. Programmers uses & and | for logical expression. Despite the introduction of their short-circuit equivalent, the non-short-circuit logical/bitwise operator precedence was not changed, the non-short-circuit operators' precedence are still equivalent with the short-circuit ones.


Long before, when I'm making a DOS(hahah showing my age) program to detect a hotkey, I tried it this way first:

   if (input & ALT_KEY == ALT_KEY) {
      printf("You pressed the shortcut combo!");
   }


Expecting it to evaluate the same with arithmetic operator precedence:
   if (a + b == C) {
      printf("True true");
   }


But alas, C is not free with old cruft, it still has B-ness in it. So you must write it this way:
   if ( (input & ALT_KEY) == ALT_KEY ) {
      printf("You pressed the shortcut combo!");
   }


If the unparenthesized expression(input & ALT_KEY == ALT_KEY) is written explicitly, it is this:
   if ( input & (ALT_KEY == ALT_KEY) ) {
      printf("You pressed the shortcut combo!");
   }

Disappointing isn't it? Not symmetrical with arithmetic operator precedence.


Backward compatibility at its finest: http://cm.bell-labs.com/cm/cs/who/dmr/chist.html

Output:
hah 0
hah 0
meh 1

hah 0
meh 1
hah 1
hah 1
hah 1

See the live example: http://ideone.com/allR6

No comments:

Post a Comment