在C#中执行位运算时,为什么必须强制转换0(零)?
我使用以下代码将我解压缩的12位值从1.5字节扩展到16位:在C#中执行位运算时,为什么必须强制转换0(零)?,c#,bitwise-operators,C#,Bitwise Operators,我使用以下代码将我解压缩的12位值从1.5字节扩展到16位: word[0] |= ((word[0] & 0x800) != 0 ? (Int16)(-4096) : (Int16)0); 如果我没有将最后一个0强制转换为Int16,编译器会抱怨如下: Warning 1 Bitwise-or operator used on a sign-extended operand; consider casting to a smaller unsigned type first Er
word[0] |= ((word[0] & 0x800) != 0 ? (Int16)(-4096) : (Int16)0);
如果我没有将最后一个0强制转换为Int16,编译器会抱怨如下:
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?)
为什么会这样?我知道C#在执行逐位运算时会将所有内容转换为int,但通常情况下,整数常量会自动指定正确的类型。例如,如果我将零赋给一个float,我就不必首先将它转换为float。我是一名C程序员,所以在回答时请记住:-)C中唯一的整数文本类型是
int
、uint
、long
和ulong
(,第2.4.4.2节)。任何文字(如0
)的类型只能推断为这4种文字中的一种(并且在没有任何额外指示的情况下,它是int
)
那么,为什么:
short s = 0;
工作?这是由于隐式常量表达式转换(第6.1.9节):
int
类型的常量表达式(§7.19)可以转换为类型sbyte
、byte
、short
、ushort
、uint
或ulong
,前提是常量表达式的值在目标类型的范围内
但是,我们在这里使用的不是一个常量表达式。因此,所有传统的C#打字规则都发挥了作用;分析条件运算符(第7.14节)时,类型为:
bool ? short : int;
编译器(不能使用上述常量表达式规则)决定该表达式的类型为
int
,因为short
可以隐式转换为int
,但不能反之亦然。这是因为文本0
被解析为int
,而不是short
,而int
不能隐式转换为short
,因此,你必须手动施放。你不必将零施放为浮点,因为int
可以隐式转换为float
@GSerg。为什么你在评论中提到float
?@HamletHakobyan,因为OP想知道为什么将零分配给浮点可以不进行施放。除了@FrédéricHamidi的评论之外条件运算符要求true
和false
部分都必须隐式转换为结果类型。好的,但是你能解释一下为什么C#不支持文本短字符吗?当编译器可以轻松地检查文本是否适合短文本时,让您强制转换文本有什么意义?我明白它在做什么,我想知道为什么。另外,你说表达式不是常量,但我不清楚你指的是哪一部分。@MoJo-我认为他们认为常量表达式规则在大多数情况下都是足够的(在我的回答中,将一个literalint
直接赋值给一个short
变量)。他们本可以支持更多类型的文字(例如0s
可能,对于short
literal),但他们没有。因为我没有参加过任何语言设计会议,所以我不能给出一个明确的“为什么”。@MoJo-re:这个恒常的表达,我同意我在回答中没有强调得太好。但基本上,我们考虑的是整个条件运算符(?:
)-因为条件((word[0]&0x800)!=0
)不是常数,所以整个表达式不是常数。如果我们写short s=false?0 : 1;
,条件运算符本身是一个常量表达式(类型为int
),因此,由于上述规则,同样可以编译。@MoJo-最后,如果您想了解有关常量表达式的更多信息,有一个完整的部分(7.19,在上面的引用中)讨论常量表达式是什么。谢谢Damien。我明白你现在的意思了,条件运算符使零也成为条件的,即使它是一个编译时常量,在C中也是如此。所以如果我使用if()语句,那么其中的赋值会被认为是条件的还是常量的?