13

为什么调用函数时会unsigned char自动提升为an ?int在下面的示例中,有一个f(int)和一个f(char)函数。编译器会强制 a和调用的unsigned char参数似乎更合乎逻辑,因为它们具有相同的位数。它正在调用,即使这意味着将参数提升为具有更多位的类型。任何指向规则定义位置的指针?标准还是编译器/平台特定?charf(char)f(int)

#include <iostream>

void f( int key )
{
    std::cout << __PRETTY_FUNCTION__ << std::endl;
}

void f( char key )
{
    std::cout << __PRETTY_FUNCTION__ << std::endl;
}

int main( int argc, char* argv[] )
{
    int a = 'a';
    char b = 'b';
    unsigned char c = 'c';

    f(a);
    f(b);
    f(c);

    return 0;
}

产生这个输出:

void f(int)
void f(char)
void f(int)
4

4 回答 4

12

因为unsigned char不能用 来表示char。例如,如果它们都是 8 位,并且您的 unsigned char 包含 value 255,则会溢出signed char- 并且有符号整数溢出会调用未定义的行为。无论如何,通常期望可打印的字符存储在char而不是unsigned char(并且C字符串的类型是char[]而不是unsigned char[]等)

因此,int必须提升 to 来表示大于 的值1 << (CHAR_BIT - 1)

于 2013-02-07T07:31:38.870 回答
7

我相信该标准的正确推导基于以下段落,该段落位于第 13.3.3 节最佳可行函数,即它是函数重载解析(非常复杂)规则的一部分。

(§13.3.3.2/4) 标准转换序列按其等级排序:精确匹配是比提升更好的转换,这是比转换更好的转换。除非以下规则之一适用,否则具有相同等级的两个转换序列是无法区分的:[...]

转换unsigned charint被归类为提升(在 §4.5 中定义;阅读以下内容时,请注意它(unsigned) char整数类型):

§4.5 整体促销
[...]

(§4.5/2) 整数类型的纯右值,而不是 bool、char16_t、char32_t 或 wchar_t,其整数转换等级 (4.13) 小于 int 的等级,如果 int 可以表示所有,则可以将其转换为 int 类型的纯右值源类型的值;否则,可以将源纯右值转换为 unsigned int 类型的纯右值。

而转换unsigned charchar不属于晋升,因为它们的等级相同:

(§4.13/1) [...] char 的等级应等于signed char 和unsigned char 的等级。[...]

相反,它被归类为积分转换(第 4.7 节),并且如上所述,在重载解决期间,提升优于转换。

于 2013-02-07T07:59:43.790 回答
3

在 C++ 标准中,char未定义为无符号或有符号(尽管大小为 1 字节),因此它是定义的实现。所以在你的实现中,我相信它是签名的字符,这就是它被提升的原因。

于 2013-02-07T08:49:31.040 回答
-1

int 和 char 在 C 和 C++ 中的范围不同,如果是 char,它的范围是 0 到 255,如果是 int,它的范围是 65535(int 的范围会因操作系统而异)。所以编译器只是把它当作int。

于 2013-02-07T07:36:54.703 回答