2013-02-07 13 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

優秀點 –

相關問題