问题
I am using the following code to sign extend a 12 bit value I unpacked from 1.5 bytes to 16 bits:
word[0] |= ((word[0] & 0x800) != 0 ? (Int16)(-4096) : (Int16)0);
If I don't cast the last zero to Int16 I get the following complaints from the compiler:
Warning 1 Bitwise-or operator used on a sign-extended operand; consider casting to a smaller unsigned type first
Error 2 Cannot implicitly convert type 'int' to 'short'. An explicit conversion exists (are you missing a cast?)
Why is this? I understand that C# converts everything to an int when doing bitwise operations, but normally integer constants are automatically given the right type. If I assign zero to a float I don't have to cast it to float first, for example. I'm a C programmer, so please keep that in mind when answering :-)
回答1:
The only types of integer literals in C# are for the types int
, uint
, long
, and ulong
(C# Language specification, version 5, section 2.4.4.2). Any literal (such as 0
) will only have its type inferred as one of those 4 (and without any extra indications, it's an int
).
So, why does:
short s = 0;
work? That would be due to Implicit constant expression conversions (section 6.1.9):
A constant-expression (§7.19) of type
int
can be converted to typesbyte
,byte
,short
,ushort
,uint
, orulong
, provided the value of the constant-expression is within the range of the destination type.
But, what we're working with here isn't a constant expression. So all of the conventional C# typing rules come into play; When analyzing the conditional operator (section 7.14), the types are:
bool ? short : int;
And the compiler (without being able to use the above constant-expression rule) decides that the type of that expression is int
, since a short
may be implicitly converted to an int
, but not vice-versa.
来源:https://stackoverflow.com/questions/23056327/why-do-i-have-to-cast-0-zero-when-doing-bitwise-operations-in-c