为什么C#的二元运算符总是返回int而不管它们的输入格式如何?
如果我有两个byte
s a
和b
,为什么会:
byte c = a & b;
关于将字节转换为int会产生编译错误吗? 即使我在a
和b
前面放置了一个显式的强制转换, a
也b
。
另外,我知道这个问题 ,但我真的不知道它是如何应用的。 这似乎是operator &(byte operand, byte operand2)
的返回类型的问题,编译器应该能够像任何其他运算符一样进行排序。
为什么C#的按位运算符总是返回int而不管它们的输入格式如何?
我总是不同意。 这是有效的, a & b
的结果类型为long
:
long a = 0xffffffffffff; long b = 0xffffffffffff; long x = a & b;
如果一个或两个参数都是long
, ulong
或uint
,则返回类型不是int
。
为什么C#的按位运算符如果输入是字节则返回int?
byte & byte
的结果是一个int,因为byte & byte
上没有&
运算符定义。 ( 来源 )
对于int
存在&
运算符,并且还存在从byte
到int
的隐式转换,因此当您写入byte1 & byte2
这实际上与写入((int)byte1) & ((int)byte2)
,并且结果是一个int
。
这种行为是IL设计的结果,IL是所有.NET编译器生成的中间语言。 虽然它支持短整数类型(byte,sbyte,short,ushort),但它只对它们进行非常有限的操作。 加载,存储,转换,创建数组,就是这样。 这不是偶然的,那些是你可以在32位处理器上有效执行的操作,当设计IL并且RISC是未来时。
二进制比较和分支操作仅适用于int32,int64,native int,本机浮点,对象和托管引用。 这些操作数在任何当前CPU内核上都是32位或64位,确保JIT编译器可以生成有效的机器代码。
您可以在Ecma 335,Partition I,第12.1章和第III部分,第1.5章中阅读更多相关信息
我在这里写了一篇关于此的更广泛的post。
没有为字节类型(等等)定义二进制运算符。 实际上,所有二进制(数字)运算符仅对以下本机类型起作用:
- INT
- UINT
- 长
- ULONG
- 浮动
- 双
- 十进制
如果涉及任何其他类型,它将使用上述之一。
这些都在C#规范5.0版(第7.3.6.2节)中 :
对于预定义的+, – ,*,/,%,&,|,^,==,!=,>,<,> =和<=二元运算符的操作数,会发生二进制数字提升。 二进制数字促销隐式地将两个操作数转换为公共类型,在非关系运算符的情况下,它也成为操作的结果类型。 二进制数字促销包括按照它们在此处显示的顺序应用以下规则:
- 如果任一操作数的类型为十进制,则另一个操作数将转换为十进制类型,否则如果另一个操作数的类型为float或double,则会发生编译时错误。
- 否则,如果任一操作数的类型为double,则另一个操作数将转换为double类型。
- 否则,如果任一操作数的类型为float,则另一个操作数将转换为float类型。
- 否则,如果任一操作数的类型为ulong,则另一个操作数将转换为ulong类型,否则如果另一个操作数的类型为sbyte,short,int或long,则会发生编译时错误。
- 否则,如果任一操作数的类型为long,则另一个操作数将转换为long类型。
- 否则,如果任一操作数的类型为uint而另一个操作数的类型为sbyte,short或int,则两个操作数都将转换为long类型。
- 否则,如果任一操作数的类型为uint,则另一个操作数将转换为类型uint。
- 否则,两个操作数都将转换为int类型。
这是因为&是在整数上定义的,而不是在字节上定义的,并且编译器隐式地将你的两个参数强制转换为int。