为什么最负的 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

5591 次浏览

The expression -2147483648 is actually applying the - operator to the constant 2147483648. On your platform, int can't store 2147483648, it must be represented by a larger type. Therefore, the expression -2147483648 is not deduced to be signed int but a larger signed type, signed long int.

Since you do not provide an overload for long the compiler is forced to choose between two overloads that are both equally valid. Your compiler should issue a compiler error about ambiguous overloads.

This is a very subtle error. What you are seeing is a consequence of there being no negative integer literals in C++. If we look at [lex.icon] we get that a integer-literal,

integer-literal
        decimal-literal integer-suffixopt
        [...]

can be a decimal-literal,

decimal-literal:
        nonzero-digit
        decimal-literal ’ opt digit

where digit is [0-9] and [1-9]0 is [1-9] and the suffix par can be one of u, U, l, L, ll, or LL. Nowhere in here does it include - as being part of the decimal literal.

In §2.13.2, we also have:

An integer literal is a sequence of digits that has no period or exponent part, with optional separating single quotes that are ignored when determining its value. An integer literal may have a prefix that specifies its base and a suffix that specifies its type. The lexically first digit of the sequence of digits is the most significant. A decimal integer literal (base ten) begins with a digit other than 0 and consists of a sequence of decimal digits.

(emphasis mine)

Which means the - in -2147483648 is the unary operator -. That means -2147483648 is actually treated as -1 * (2147483648). Since 2147483648 is one too many for your int it is promoted to a long int and the ambiguity comes from that not matching.

If you want to get the minimum or maximum value for a type in a portable manner you can use:

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

Expanding on others' answers


To clarify why the OP is confused, first: consider the signed int binary representation of 2147483647, below.

Largest signed int




Next, add one to this number: giving another signed int of -2147483648 (which the OP wishes to use) Smallest signed int



Finally: we can see why the OP is confused when -2147483648 compiles to a long int instead of a signed int, since it clearly fits in 32 bits.

But, as the current answers mention, the unary operator (-) is applied after resolving 2147483648 which is a long int and does NOT fit in 32 bits.