For some reason, I am simply not understanding (or seeing) why this works:
UInt32 a = 0x000000FF;
a &= ~(UInt32)0x00000001;
but this does n
Because §14.6.4 of the Standard (ISO 23270) says:
14.6.4 Bitwise complement operator
For an operation of the form
~x
, unary operator overload resolution (§14.2.3) is applied to select a specific operator implementation. The operand is converted to the parameter type of the selected operator, and the type of the result is the return type of the operator. The predefined bitwise complement operators are:int operator ~(int x); uint operator ~(uint x); long operator ~(long x); ulong operator ~(ulong x);
For each of these operators, the result of the operation is the bitwise complement of
x
.
If you work through the unary operator overload resolution specified in §14.2.3, you'll find that, as noted by §14.2.6.1 ("Unary numeric promotions"), which is informative rather than normative, that the net effect is this:
Unary numeric promotion occurs for the operands of the predefined
+
,–
, and~
unary operators. Unary numeric promotion simply consists of converting operands of typesbyte
,byte
,short
,ushort
, orchar
to typeint
.
So despite your cast, ~(ushort)0x0001
, the compiler is smart enough to note the constant expression and do constant folding, meaning that the end result is a signed 32-bit integer with a value of -2, or 0xFFFFFFFE
. And...
Since the expression, a &= b ;
is exactly equivalent to a = a & b ;
, you are trying to do a bitwise AND of a ushort
and an int
. The ushort
is upcast to an int and the bitwise AND evaluated, yielding a signed 32-bit integer result.
.
.
.
which can't be assigned to a ushort
(unsigned 16-bit).
That is why.