2013-02-07 14 views
13

为什么调用函数时的unsigned char自动提升为int?在下面的例子中有一个f(int)f(char)功能。这似乎更符合逻辑,编译器将强制那些unsigned char参数传递给char并呼吁f(char),因为它们具有相同的位数。它改为调用f(int),即使这意味着将参数提升为具有更多位的类型。任何指向规则定义的指针?标准或编译器/平台特定?无符号字符在函数调用时自动提升为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) 
+9

'unsigned char'的所有可能值都可以用'int'表示。它们不能全部由签名的“char”表示。 –

回答

12

因为unsigned char不能通过char来表示。举例来说,如果他们都是8位,和你的无符号的字符包含值255,即溢出signed char - 并签署整数溢出调用未定义的行为。无论如何,可打印字符一般预期要被存储在char和不unsigned char(和C字符串类型char[]和不unsigned char[]的等)

所以促进向int必须代表值比1 << (CHAR_BIT - 1)更大。

+2

但是请注意M3taSpl0it的回答如下:是否有符号或无符号是实现确定的,理论上这个代码在编译器行为上会有所不同。 –

+0

@JackAidley是的,它会,但是在这个特殊的例子中(并且在大多数实现中)它是被签名的。 – 2013-02-07 12:02:38

+0

事实上,它仍然值得注意一般 –

-1

int和炭在范围内的在C和C++只是不同,如果它烧焦的范围从0到255,并且如果INT,它有它的范围等65535(范围为int将与OS变化)。所以编译器只是把它当作int。

+3

char(有符号)实际上的范围从-128到127,它与unsigned char不一样,范围从0到255. – KBart

+0

因此,当作为参数传递时,编译器会区分签名和未签名? –

+1

查看[这里](http://www.arm.linux.org.uk/docs/faqs/signedchar.php)为例。它基于ARM,但许多平台都应该面临同样的问题。通常混合它们并不是一个好主意。 – KBart

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)以外的整数类型的prvalue小于INT的秩可以被转换成一个int类型的prvalue如果INT可以表示源类型的所有值;否则,可以将源prvalue转换为unsigned int类型的prvalue。

而转换到unsigned charchar未被分类为促进因为他们的行列是相同的:

(§4.13/ 1)[...]炭的秩必须等于的秩signed char和unsigned char。 [...]

它被归类为积分转换(§4.7)代替,并且,如上所述,促进优于过载解析期间转换。

3

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

+0

优秀点 –

相关问题