为什么最负的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可以是uUlLllLL 。 这里没有包括-作为十进制文字的一部分。

在§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为什么困惑,首先 :考虑下面的2147483647signed int二进制表示。

最大的签名int


接下来,给这个数字加上一个 :给出另一个-2147483648 signed int (OP希望使用) 最小的有符号整数


最后:-2147483648编译为long int而不是signed int ,我们可以看到为什么OP会感到困惑,因为它显然适合于32位。

但是,正如现在的答案所提到的那样,一元运算符( -parsing2147483648 之后被应用这是一个long int ,不适合32位。