私は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
これは非常に微妙なエラーです。あなたが見ているのは、C++に負の整数リテラルがないことの結果です。 [Lex.icon]を見ると、integer-literalが得られます。
整数リテラル
decimal-literal integer-suffixopt
[...]
decimal-literal、
decimal-literal:
非ゼロ桁
decimal-literal ’ opt 桁
ここで、digitは[0-9]
であり、nonzero-digitは[1-9]
であり、接尾辞par u
、U
、l
、L
、ll
、またはLL
のいずれかです。ここのどこにも、10進リテラルの一部として-
が含まれていません。
§2.13.2では、次のものもあります。
integer literalは、ピリオドまたは指数部を持たない数字のシーケンスであり、値を決定するときに無視されるオプションの単一引用符を分離します。整数リテラルには、ベースを指定するプレフィックスと、タイプを指定するサフィックスが含まれる場合があります。数字列の字句的に最初の数字が最も重要です。 Adecimal整数リテラル(10進数)は0以外の数字で始まり、10進数のシーケンスで構成されます。
(エンファシス鉱山)
つまり、-
の-2147483648
は、単項operator -
です。つまり、-2147483648
は実際には-1 * (2147483648)
として扱われます。 2147483648
はint
には多すぎるため、long int
に昇格し、一致しないことからあいまいさが生じます。
型の最小値または最大値を移植可能な方法で取得する場合は、次を使用できます。
std::numeric_limits<type>::min(); // or max()
式-2147483648
は、実際に-
演算子を定数2147483648
に適用しています。プラットフォームでは、int
は2147483648
を格納できません。より大きな型で表す必要があります。したがって、式-2147483648
はsigned int
であると推定されませんが、より大きな符号付き型signed long int
であると推定されます。
long
のオーバーロードを提供しないため、コンパイラーは両方とも等しく有効な2つのオーバーロードから選択するように強制されます。コンパイラは、あいまいなオーバーロードに関するコンパイラエラーを発行する必要があります。