web-dev-qa-db-ja.com

なぜ最も負のint値があいまいな関数のオーバーロードに関するエラーを引き起こすのですか?

私はC++での関数のオーバーロードについて学んでいますが、これに遭遇しました:

_void display(int a)
{
    cout << "int" << endl;
}

void display(unsigned a)
{
    cout << "unsigned" << endl;
}

int main()
{
    int i = -2147483648;
    cout << i << endl; //will display -2147483648
    display(-2147483648);
}
_

私が理解したことから、int範囲(私の場合、intは4バイト)で指定された値はdisplay(int)を呼び出し、この範囲外の値はあいまいになります(コンパイラが呼び出す関数を決定できないためです)。最小値を除くint値の全範囲で有効です。つまり、エラーでコンパイルが失敗する_-2147483648_

オーバーロードされたdisplay(long int)の呼び出しがあいまいです

ただし、intに同じ値を取り、値を出力すると_2147483648_が得られます。私は文字通りこの動作と混同しています。

最も負の数が渡された場合にのみ、この動作が観察されるのはなぜですか? (shortが_-32768_と一緒に使用される場合の動作は同じです-実際、負の数と正の数が同じバイナリ表現を持っている場合)

使用コンパイラ:g ++(GCC)4.8.5

88
infinite loop

これは非常に微妙なエラーです。あなたが見ているのは、C++に負の整数リテラルがないことの結果です。 [Lex.icon]を見ると、integer-literalが得られます。

整数リテラル
decimal-literal integer-suffixopt
[...]

decimal-literal

decimal-literal:
非ゼロ桁
decimal-literal ’ opt 桁

ここで、digit[0-9]であり、nonzero-digit[1-9]であり、接尾辞par uUlLll、またはLLのいずれかです。ここのどこにも、10進リテラルの一部として-が含まれていません。

§2.13.2では、次のものもあります。

integer literalは、ピリオドまたは指数部を持たない数字のシーケンスであり、値を決定するときに無視されるオプションの単一引用符を分離します。整数リテラルには、ベースを指定するプレフィックスと、タイプを指定するサフィックスが含まれる場合があります。数字列の字句的に最初の数字が最も重要です。 Adecimal整数リテラル(10進数)は0以外の数字で始まり、10進数のシーケンスで構成されます。

(エンファシス鉱山)

つまり、--2147483648は、単項operator -です。つまり、-2147483648は実際には-1 * (2147483648)として扱われます。 2147483648intには多すぎるため、long intに昇格し、一致しないことからあいまいさが生じます。

型の最小値または最大値を移植可能な方法で取得する場合は、次を使用できます。

std::numeric_limits<type>::min();  // or max()
143
NathanOliver

-2147483648は、実際に-演算子を定数2147483648に適用しています。プラットフォームでは、int2147483648を格納できません。より大きな型で表す必要があります。したがって、式-2147483648signed intであると推定されませんが、より大きな符号付き型signed long intであると推定されます。

longのオーバーロードを提供しないため、コンパイラーは両方とも等しく有効な2つのオーバーロードから選択するように強制されます。コンパイラは、あいまいなオーバーロードに関するコンパイラエラーを発行する必要があります。

36

他者の回答を拡大する


OPが混乱する理由を明確にするために、まず:以下のsigned int2147483647バイナリ表現を検討します。

Largest signed int




次に、この番号に1を追加signed intの別の-2147483648を与える(OPが使用したい) Smallest signed int



最後に:-2147483648long intではなくsigned intにコンパイルされるときにOPが混乱する理由がわかります。これは明らかに32ビットに収まるからです。

しかし、現在の答えが言及しているように、単項演算子(-)が適用されますafter2147483648であり、32ビットに収まらないlong intを解決します。

4
bunkerdive