1

考虑以下代码:

void f(byte x) {print("byte");}
void f(short x) {print("short");}
void f(int x) {print("int");}

void main() {
    byte b1, b2;
    short s1, s2;

    f(b1 + b2); // byte + byte = int
    f(s1 + s2); // short + short = int
}

在 C++、C#、D 和 Java 中,两个函数调用都解析为“int”重载……我已经意识到这是“规范中的”,但为什么语言会这样设计呢?我正在寻找更深层的原因。

对我来说,结果是能够表示两个操作数的所有可能值的最小类型是有意义的,例如:

byte + byte --> byte
sbyte + sbyte --> sbyte
byte + sbyte --> short
short + short --> short
ushort + ushort --> ushort
short + ushort --> int
// etc...

这将消除不方便的代码,例如short s3 = (short)(s1 + s2),以及 IMO 更加直观和易于理解。

这是 C 时代遗留下来的遗产,还是当前行为有更好的理由?

4

2 回答 2

2

Quoted from this MSDN blog post:

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

In this fantasy world, the value of i would be 16! Why? Because the two operands to the + operator are both bytes, so the sum "b+c" is computed as a byte, which results in 16 due to integer overflow. (And, as I noted earlier, integer overflow is the new security attack vector.)

Similarly,

int j = -b;

would result in j having the value 224 and not -32, for the same reason.

Is that really what you want?

...

So no matter how you slice it, you're going to have to insert annoying casts. May as well have the language err on the side of safety (forcing you to insert the casts where you know that overflow is not an issue) than to err on the side of silence (where you may not notice the missing casts until your Payroll department asks you why their books don't add up at the end of the month).

Also, it's worth noting that adding in these casts only means extra typing, and nothing more. Once the JIT (or possibly the static compiler itself) reduces the arithmetic operation to a basic processor instruction, there's nothing clever going on - it's just whether the number gets treated as an int or byte.

This is a good question, however... not at all an obvious one. Hope that makes the reasons clear for you now.

于 2009-05-07T19:39:23.003 回答
0

一套更好的规则恕我直言,如果规定移位运算符只能与恒定移位值一起使用(对可变移位量使用移位函数),则任何算术表达式的结果都应始终评估为就好像它被处理过一样最大可能的有符号或无符号类型,前提是可以静态保证给出正确的结果(在最大的有符号类型可能不够用的情况下,将应用稍微棘手的规则)。如果移位操作数只允许是常量,那么在编译时可以很容易地确定任何操作数的最大有意义值可能是什么,所以我认为编译器没有任何充分的理由不查看运算符的结果是如何使用的在决定运营商的实施。

于 2010-12-08T00:01:11.113 回答