我正在学习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
答案 0 :(得分:141)
这是一个非常微妙的错误。你所看到的是C ++中没有负整数文字的结果。如果我们查看[lex.icon],我们会得到一个 integer-literal ,
整数字面
decimal-literal integer-suffix opt
[...]
可以是 decimal-literal ,
十进制字面:
非零位数
decimal-literal' opt 数字
其中数字为[0-9]
且非零数字为[1-9]
,后缀par可为u
之一,{ {1}},U
,l
,L
或ll
。这里没有任何地方包含LL
作为十进制文字的一部分。
在§2.13.2中,我们也有:
整数文字是一个没有句点或指数部分的数字序列,可选地分隔单引号,在确定其值时会被忽略。整数文字可以具有指定其基数的前缀和指定其类型的后缀。数字序列的词汇第一个数字是最重要的。 十进制整数文字(十进制)以0以外的数字开头,由一系列十进制数字组成。
(强调我的)
这意味着-
中的-
是一元-2147483648
。这意味着operator -
实际上被视为-2147483648
。由于-1 * (2147483648)
对于2147483648
来说太多了int
,因此会将其提升为long int
,并且歧义来自于不匹配。
如果您想以便携方式获取某个类型的最小值或最大值,可以使用:
std::numeric_limits<type>::min(); // or max()
答案 1 :(得分:35)
表达式-2147483648
实际上是将-
运算符应用于常量2147483648
。在您的平台上,int
无法存储2147483648
,它必须以更大的类型表示。因此,表达式-2147483648
不会推断为signed int
,而是更大的签名类型signed long int
。
由于您没有为long
提供重载,因此编译器必须在两个同样有效的重载之间进行选择。您的编译器应该发出有关模糊重载的编译器错误。
答案 2 :(得分:4)