Expressions "j = ++(i | i); and j = ++(i & i); should be a lvalue error? Expressions "j = ++(i | i); and j = ++(i & i); should be a lvalue error? c c

Expressions "j = ++(i | i); and j = ++(i & i); should be a lvalue error?


You are right that it should not compile, and on most compilers, it does not compile.
(Please specify exactly which compiler/version is NOT giving you a compiler error)

I can only hypothesize that the compiler knows the identities that (i | i) == i and (i & i) == i and is using those identities to optimize away the expression, just leaving behind the variable i.

This is just a guess, but it makes a lot of sense to me.


This is a bug that has been addressed in more recent GCC versions.

It's probably because the compiler optimizes i & i to i and i | i to i. This also explains why the xor operator didn't work; i ^ i would be optimized to 0, which is not a modifiable lvalue.


C11 (n1570), § 6.5.3.1 Prefix increment and decrement operators
The operand of the prefix increment or decrement operator shall have atomic, qualified, or unqualified real or pointer type, and shall be a modifiable lvalue.

C11 (n1570), § 6.3.2.1 Lvalues, arrays, and function designators
A modifiable lvalue is an lvalue that does not have array type, does not have an incomplete type, does not have a const- qualified type, and if it is a structure or union, does not have any member (including, recursively, any member or element of all contained aggregates or unions) with a const- qualified type.

C11 (n1570), § 6.3.2.1 Lvalues, arrays, and function designators
An lvalue is an expression (with an object type other than void) that potentially designates an object.

C11 (n1570), § 3. Terms, definitions, and symbols
Object: Region of data storage in the execution environment, the contents of which can represent values

As far as I know, potentially means "capable of being but not yet in existence". But (i | i) is not capable of referencing a region a data storage in the execution environment. Therefore it is not an lvalue. This seems to be a bug in an old gcc version, fixed since. Update your compiler!