8

この興味深い質問に基づいて: Nicholas Carey's answerに記載されているように、int と uint を追加し、一定の折り畳みをいじくり回すと、一見一貫性のないコンパイラの動作に遭遇しました。

次のコード スニペットを検討してください。

int i = 1;
uint j = 2;
var k = i - j;

ここで、コンパイラは に正しく解決kされlongます。この特定の動作は、前述の質問への回答で説明されているように、仕様で明確に定義されています。

私にとって驚くべきことは、リテラル定数または一般的な定数を扱うときに動作が変化することです。Nicholas Carey の回答を読んで、動作に一貫性がない可能性があることに気付いたので、確認して十分に確認しました。

const int i = 1;
const uint j = 2;
var k = i - j; //Compile time error: The operation overflows at compile time in checked mode.
k = 1 - 2u; //Compile time error: The operation overflows at compile time in checked mode.

kこの場合は に解決されUint32ます。

定数を扱うときに動作が異なる理由はありますか、それともこれはコンパイラの小さいながらも不幸な「バグ」(より適切な用語の欠如) ですか?

4

2 に答える 2

3

こちらの回答をご覧ください

問題は、const を使用していることです。

const がある場合の実行時の動作は、リテラルの場合とまったく同じであるか、コード内にこれらの数値を単にハードコーディングしたかのようになります。したがって、数値は 1 と 2 であるため、1 は範囲内にあるため、Uint32 にキャストされます。 uint32. 次に、uint32 で 1 - 2 を減算しようとすると、1u - 2u = +4,294,967,295 (0xFFFFFFFF) であるため、オーバーフローします。

コンパイラはリテラルを見て、他の変数とは異なる解釈をすることができます。const は決して変更されないため、他の方法では作成できなかった保証を作成できます。この場合、1 が uint の範囲内にあることを保証できるため、暗黙的にキャストできます。通常の状況(const なし)では、その保証はできませんが、

signed int の範囲は -2,147,483,648 (0x80000000) から +2,147,483,647 (0x7FFFFFFF) です。

unsigned int の範囲は 0 (0x00000000) から +4,294,967,295 (0xFFFFFFFF) です。

話の教訓、const と var を混在させるときは注意してください。予期しない結果が得られる可能性があります。

于 2014-10-15T15:39:45.893 に答える