看看这段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数组)更快(因为缓存命中)。但是大量的字节强制转换散布在代码中,使得代码更加难以阅读。


当前回答

我想我以前在什么地方见过这个。从这篇文章,旧的新事物:

假设我们生活在一个幻想的世界 对'byte'的操作导致了什么 “字节”。

byte b = 32;
byte c = 240;
int i = b + c; // what is i?

在这个幻想世界里,i的值 应该是16岁!为什么?因为这两个 +操作符的操作数都是 字节,因此“b+c”的和计算为 一个字节,由于 整数溢出。(而且,正如我所指出的 之前,整数溢出是新的 安全攻击向量。)

编辑:Raymond实质上是在捍卫C和c++最初采用的方法。在评论中,他从语言向后兼容的角度为c#采用了相同的方法进行了辩护。

其他回答

这是由于溢出和携带。

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

例子:

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

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

代码片段的第三行:

byte z = x + y;

实际上意味着

byte z = (int) x + (int) y;

因此,对字节没有+操作,字节首先被转换为整数,两个整数相加的结果是一个(32位)整数。

This was probably a practical decision on the part of the language designers. After all, an int is an Int32, a 32-bit signed integer. Whenever you do an integer operation on a type smaller than int, it's going to be converted to a 32 bit signed int by most any 32 bit CPU anyway. That, combined with the likelihood of overflowing small integers, probably sealed the deal. It saves you from the chore of continuously checking for over/under-flow, and when the final result of an expression on bytes would be in range, despite the fact that at some intermediate stage it would be out of range, you get a correct result.

另一种想法是:必须模拟这些类型上的溢出/欠流,因为它不会自然地发生在最可能的目标cpu上。何苦呢?

从.NET框架代码:

// bytes
private static object AddByte(byte Left, byte Right)
{
    short num = (short) (Left + Right);
    if (num > 0xff)
    {
        return num;
    }
    return (byte) num;
}

// shorts (int16)
private static object AddInt16(short Left, short Right)
{
    int num = Left + Right;
    if ((num <= 0x7fff) && (num >= -32768))
    {
        return (short) num;
    }
    return num;
}

使用。net 3.5及以上版本进行简化:

public static class Extensions 
{
    public static byte Add(this byte a, byte b)
    {
        return (byte)(a + b);
    }
}

现在你可以做:

byte a = 1, b = 2, c;
c = a.Add(b);

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

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

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

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