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

このMSDNブログ投稿からの引用:

バイトb=32; バイトc=240; int i = b + c; //私は何ですか?

このファンタジー世界では、iの値は16になります!なんで?+演算子の2つのオペランドは両方ともバイトであるため、合計「b + c」はバイトとして計算され、整数のオーバーフローのために16になります。(そして、先に述べたように、整数のオーバーフローは新しいセキュリティ攻撃ベクトルです。)

同様に、

int j = -b;

同じ理由で、jの値は-32ではなく224になります。

それは本当にあなたが望むものですか?

..。

したがって、どのようにスライスしても、迷惑なキャストを挿入する必要があります。沈黙の側(給与部門までキャストの欠落に気付かない可能性がある)よりも、安全の側(オーバーフローが問題ではないことがわかっている場所にキャストを挿入するように強制する)の言語エラーがある可能性があります彼らの本が月末に合計されない理由を尋ねます)。

また、これらのキャストを追加することは、余分な入力を意味するだけであり、それ以上のことは何も意味しないことに注意してください。JIT(または静的コンパイラ自体)が算術演算を基本的なプロセッサ命令に還元すると、賢いことは何も起こりません。数値がまたはとして扱われるかどうかだけintですbyte

これは良い質問ですが...まったく明白な質問ではありません。それが今あなたに理由を明らかにすることを願っています。

于 2009-05-07T19:39:23.003 に答える
0

シフト演算子を一定のシフト値でのみ使用できる(可変シフト量のシフト関数を使用する)場合、IMHOのより適切なルールのセットは、算術式の結果が常に次のように処理されたかのように評価されることです。正しい結果が得られることが静的に保証されている場合は、可能な限り最大の符号付きまたは符号なしタイプ(最大の符号付きタイプでは不十分な場合は、少し注意が必要なルールが適用されます)。シフトオペランドは定数のみが許可されている場合、コンパイル時にオペランドの最大の意味のある値を簡単に判断できるため、コンパイラが演算子の結果がどのように使用されるかを確認しない理由はわかりません。演算子の実装を決定する際に。

于 2010-12-08T00:01:11.113 に答える