为什么最负的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)
调用是不明确的
但是将相同的值2147483648
int
并打印该值将会产生2147483648
。 我真的与这种行为混淆。
为什么只有当最负数字通过时才会观察到这种行为? (如果一个short
和-32768
使用,行为是一样的 – 事实上,在任何情况下,负数和正数都有相同的二进制表示)
使用的编译器:g ++(GCC)4.8.5
这是一个非常微妙的错误。 你所看到的是C ++中没有负整型文字的结果。 如果我们看一下[lex.icon],我们得到一个整数文字 ,
整数字面
十进制文字整数后缀select
[…]
可以是十进制文字 ,
十进制文字:
非零数字
十进制文字' select数字
其中数字是[0-9]
, 非零数字是[1-9]
,后缀par可以是u
, U
, l
, L
, ll
或LL
。 这里没有包括-
作为十进制文字的一部分。
在§2.13.2中,我们也有:
整数字面量是一个没有周期或指数部分的数字序列,可选地分隔单引号,在确定其值时被忽略。 整数字面量可以有一个前缀,用来指定其基数和一个指定其types的后缀。 数字序列的词汇第一位是最重要的。 十进制整数文字( 十进制 )以0以外的数字开头,由十进制数字组成。
(重点是我的)
这意味着-
在-2147483648
是一元运算operator -
。 这意味着-2147483648
实际上被视为-1 * (2147483648)
。 因为2147483648
对于你的int
来说太多了,所以它被提升为一个long int
并且由于不匹配而产生歧义。
如果您想以便携方式获取某个types的最小值或最大值,可以使用:
std::numeric_limits<type>::min(); // or max()
expression式-2147483648
实际上将-
运算符应用于常量2147483648
。 在你的平台上, int
不能存储2147483648
,它必须用更大的types来表示。 因此,expression式-2147483648
不是推导为有signed int
而是更大的有符号types,可能是有signed long int
。
由于您不提供long
的重载,因此编译器不得不在两个同等(有效)的重载之间进行select。 您的编译器应该发出关于模糊重载的编译器错误。
扩大他人的答案
为了弄清OP为什么困惑,首先 :考虑下面的2147483647
的signed int
二进制表示。
接下来,给这个数字加上一个 :给出另一个-2147483648
signed int
(OP希望使用)
最后:当-2147483648
编译为long int
而不是signed int
,我们可以看到为什么OP会感到困惑,因为它显然适合于32位。
但是,正如现在的答案所提到的那样,一元运算符( -
) 在parsing2147483648
之后被应用,这是一个long int
,不适合32位。