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