看看这段c#代码:

byte x = 1;
byte y = 2;
byte z = x + y; // ERROR: Cannot implicitly convert type 'int' to 'byte'

在字节(或短)类型上执行的任何数学运算的结果都隐式地转换回整数。解决方案是显式地将结果转换回一个字节:

byte z = (byte)(x + y); // this works

我想知道的是为什么?是建筑吗?哲学吗?

我们有:

Int + Int = Int 长+长=长 浮+浮=浮 Double + Double = Double

所以为什么不呢:

字节+字节=字节 空头+空头=空头?

一点背景知识:我正在对“小数字”(即< 8)执行一个长列表的计算,并将中间结果存储在一个大数组中。使用字节数组(而不是int数组)更快(因为缓存命中)。但是大量的字节强制转换散布在代码中,使得代码更加难以阅读。


当前回答

C#

ECMA-334指出,只有在int+int、uint+uint、long+long和ulong+ulong (ECMA-334 14.7.4)上,加法才被定义为合法。因此,这些是关于14.4.2需要考虑的候选操作。由于存在从byte到int、uint、long和ulong的隐式强制转换,所有加法函数成员都是14.4.2.1下适用的函数成员。我们必须根据14.4.2.3中的规则找到最佳隐式转换:

将(C1)转换为int(T1)比将(C2)转换为uint(T2)或ulong(T2)更好,因为:

如果T1是int, T2是uint或ulong, C1是更好的转换。

将(C1)转换为int(T1)比将(C2)转换为long(T2)更好,因为从int转换为long存在隐式转换:

如果存在从T1到T2的隐式转换,且不存在从T2到T1的隐式转换,则C1是更好的转换。

因此使用int+int函数,该函数返回int型。

可以说它深埋在c#规范中。

CLI

CLI只对6种类型(int32、native int、int64、F、O和&)起作用。(ECMA-335分区3节1.5)

Byte (int8)不是这些类型之一,在添加之前会自动强制转换为int32。(ECMA-335分区3节1.6)

其他回答

这是由于溢出和携带。

如果您将两个8位数字相加,它们可能会溢出到第9位。

例子:

  1111 1111
+ 0000 0001
-----------
1 0000 0000

我不确定,但我假设int型、long型和double型被赋予了更多的空间,因为它们确实相当大。此外,它们是4的倍数,这对计算机来说更有效,因为内部数据总线的宽度是4字节或32位(64位现在越来越普遍)宽。Byte和short的效率稍低,但它们可以节省空间。

除了所有其他伟大的评论,我想我要添加一个小花絮。很多评论都想知道为什么int、long和几乎任何其他数字类型都不遵循这个规则…返回一个“更大”的类型以响应算术。

A lot of answers have had to do with performance (well, 32bits is faster than 8bits). In reality, an 8bit number is still a 32bit number to a 32bit CPU....even if you add two bytes, the chunk of data the cpu operates on is going to be 32bits regardless...so adding ints is not going to be any "faster" than adding two bytes...its all the same to the cpu. NOW, adding two ints WILL be faster than adding two longs on a 32bit processor, because adding two longs requires more microops since you're working with numbers wider than the processors word.

I think the fundamental reason for causing byte arithmetic to result in ints is pretty clear and straight forward: 8bits just doesn't go very far! :D With 8 bits, you have an unsigned range of 0-255. That's not a whole lot of room to work with...the likelyhood that you are going to run into a bytes limitations is VERY high when using them in arithmetic. However, the chance that you're going to run out of bits when working with ints, or longs, or doubles, etc. is significantly lower...low enough that we very rarely encounter the need for more.

从字节到int的自动转换是合乎逻辑的,因为字节的规模是如此之小。从整型到长型,从浮点数到双精度浮点数等自动转换是不符合逻辑的,因为这些数字具有显著的比例。

我认为这是一个关于哪种操作更常见的设计决策……如果byte+byte = byte,可能更多的人会被强制转换为int类型的结果所困扰。

没有为字节定义加法。所以它们被转换为int类型进行加法运算。对于大多数数学运算和字节来说都是如此。(请注意,这是在旧语言中使用的方式,我假设它在今天仍然适用)。

在添加字节和将结果截断回字节时显示一些低效的答案是不正确的。X86处理器有专门为8位数的整数运算而设计的指令。

事实上,对于x86/64处理器,执行32位或16位操作的效率低于64位或8位操作,因为必须对操作数前缀字节进行解码。在32位机器上,执行16位操作需要同样的代价,但是仍然有专门的8位操作的操作码。

许多RISC架构都有类似的本地字/字节高效指令。那些通常没有存储并转换为某个比特长度的signed值的类型。

换句话说,这个决定必须基于对字节类型用途的感知,而不是由于硬件的底层低效率。