为什么最负的 int 值会导致模棱两可的函数重载错误?

我正在学习 C++ 中的函数重载并遇到了这个问题:

I'm learning about function overloading in C++ and came across this:

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 编译失败并出现错误

From what I understood, any value given in the int range (in my case int is 4 byte) will call display(int) and any value outside this range will be ambiguous (since the compiler cannot decide which function to call). It is valid for the complete range of int values except its min value i.e. -2147483648 where compilation fails with the error

调用重载的display(long int)不明确

但是对 int 取相同的值并打印该值会得到 2147483648.我真的对这种行为感到困惑.

But taking the same value to an int and printing the value gives 2147483648. I'm literally confused with this behavior.

为什么只有在传递最大负数时才会观察到这种行为?(如果 short-32768 一起使用,行为是相同的 - 事实上,在负数和正数具有相同二进制表示的任何情况下)

Why is this behavior observed only when the most negative number is passed? (The behavior is the same if a short is used with -32768 - in fact, in any case where the negative number and positive number have the same binary representation)

使用的编译器:g++ (GCC) 4.8.5

Compiler used: g++ (GCC) 4.8.5

推荐答案

这是一个非常微妙的错误.您所看到的是 C++ 中没有负整数文字的结果.如果我们查看 [lex.icon] 我们会得到一个 integer-literal,

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,

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

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

可以是十进制文字,

十进制文字:
        非零位
        decimal-literal ' opt digit

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

其中 digit 是 [0-9] 并且 nonzero-digit 是 [1-9] 并且后缀par可以是uUlLll 或 LL.这里没有任何地方包含 - 作为十进制文字的一部分.

where digit is [0-9] and nonzero-digit 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.

在 §2.13.2 中,我们还有:

In §2.13.2, we also have:

整数文字 是一个没有句点或指数部分的数字序列,在确定其值时可以忽略单引号.整数文字可能有一个指定其基数的前缀和一个指定其类型的后缀.数字序列的词汇第一个数字是最重要的.十进制整数文字(以十为底)以非 0 的数字开头,由一系列十进制数字组成.

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.

(强调我的)

这意味着-2147483648中的-是一元操作符-.这意味着 -2147483648 实际上被视为 -1 * (2147483648).由于 2147483648 对于您的 int 来说太多了,它被提升为 long int 并且歧义来自不匹配.

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()

相关文章