Error when trying to perform a bitwise not (~) on a UInt16 in C#

梦想的初衷 提交于 2019-12-31 05:27:08

问题


For some reason, I am simply not understanding (or seeing) why this works:

UInt32 a = 0x000000FF;
a &= ~(UInt32)0x00000001;

but this does not:

UInt16 a = 0x00FF;
a &= ~(UInt16)0x0001;

it gives the error 'constant value -(some number) cannot be converted to a UInt16'. Can someone explain why this is and how to work around the problem?


回答1:


The bitwise negation promotes the result to a int, despite the cast. You can overcome this by bitwise and-ing the result of the bitwise negation to the lower 16 bits, like this: ~0x0001 & 0xFFFF.




回答2:


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 type sbyte, byte, short, ushort, or char to type int.

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.




回答3:


Your expression evaluated at compile time and as result overflow error is detected and blocking compilation.

Sample below show that run-time does not throw exception by default:

UInt16 a = 0x00FF;
UInt16 b = 0x0001;
a &= (UInt16)~b; 

Note that your code also was converting int (as result of ~ operation on UInt16 converted to int) - so I moved ~ before cast.

Why: C# compiler generally tries to prevent unintentional code behavior if possible, which combined with all bit-wise operations defined on int/uint/long/ulong and compile time constant evaluation leads to this compile time error.



来源:https://stackoverflow.com/questions/21174271/error-when-trying-to-perform-a-bitwise-not-on-a-uint16-in-c-sharp

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!