2013-02-07 62 views
13

Tại sao một số điện thoại unsigned char được tự động thăng cấp lên một số int khi gọi một hàm? Trong ví dụ bên dưới, có một hàm f(int) và hàm f(char). Có vẻ logic hơn là trình biên dịch sẽ ép buộc đối số unsigned char thành số char và gọi f(char) vì chúng có cùng số bit. Nó được gọi là f(int) thay vào đó, ngay cả khi đó có nghĩa là thúc đẩy các đối số cho một loại với nhiều bit hơn. Bất kỳ con trỏ đến nơi quy tắc được xác định? Tiêu chuẩn hoặc trình biên dịch/nền tảng cụ thể?char chưa được ký tự động được thăng cấp thành int trong cuộc gọi hàm, tại sao?

#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; 
} 

Tạo đầu ra này:

void f(int) 
void f(char) 
void f(int) 
+9

Tất cả các giá trị có thể có của một 'unsigned char' có thể được biểu diễn bằng' int'. Chúng không thể được biểu diễn bằng một ký tự 'char'. –

Trả lời

12

unsigned char không thể được đại diện bởi char. Ví dụ, nếu cả hai đều là 8 bit và char chưa ký của bạn chứa giá trị 255, tràn qua signed char - và tràn số nguyên đã ký sẽ gọi hành vi không xác định. Dù sao, các ký tự in thường được dự kiến ​​sẽ được lưu trữ trong char và không unsigned char (và C chuỗi là kiểu char[] và không unsigned char[], vv)

Vì vậy, việc bổ nhiệm vào int là cần thiết để đại diện cho các giá trị lớn hơn 1 << (CHAR_BIT - 1).

+2

Nhưng lưu ý câu trả lời của M3taSpl0it bên dưới: cho dù 'char' được ký hoặc chưa ký được thực hiện xác định như vậy, theo lý thuyết, mã này sẽ thay đổi trong hành vi của trình biên dịch. –

+0

@JackAidley Có, nó sẽ, nhưng trong ví dụ cụ thể này (và trong hầu hết các triển khai) nó được ký kết. –

+0

Thật vậy, nhưng nó vẫn đáng chú ý nói chung –

-1

int và char chỉ khác nhau trong phạm vi C và C++, nếu char nằm trong khoảng từ 0 đến 255 và nếu int, nó có phạm vi 65535 (phạm vi int sẽ thay đổi theo OS). Vì vậy, trình biên dịch chỉ coi nó là int.

+3

char (ký) thực sự dao động từ -128 đến 127 và nó không giống như char unsigned, trong khoảng từ 0 đến 255. – KBart

+0

Vì vậy, trong khi đi qua như đối số, trình biên dịch phân biệt giữa đã ký và chưa ký? –

+1

xem [tại đây] (http://www.arm.linux.org.uk/docs/faqs/signedchar.php) để biết ví dụ. Nó dựa trên ARM, nhưng nhiều nền tảng phải đối mặt với cùng một vấn đề. Nói chung nó không phải là ý tưởng tốt để trộn chúng. – KBart

7

Tôi tin rằng dẫn xuất chính xác từ Tiêu chuẩn dựa trên đoạn dưới đây, được tìm thấy trong phần 13.3.3 Các chức năng khả thi tốt nhất, tức là một phần của các quy tắc (rất phức tạp).

(§13.3.3.2/4) Chuỗi chuyển đổi chuẩn được sắp xếp theo thứ hạng của chúng: Đối sánh chính xác là chuyển đổi tốt hơn Quảng cáo, chuyển đổi tốt hơn Chuyển đổi. Hai chuỗi chuyển đổi với cùng một cấp bậc không thể phân biệt trừ khi một trong những quy tắc sau đây được áp dụng: [...]

Chuyển đổi unsigned char để int được phân loại là xúc tiến (quy định tại §4.5; khi đọc dưới đây, lưu ý rằng (unsigned) char là một loại nguyên):

§4.5 chương trình khuyến mãi Integral
[...]

(§4.5/2) Giá trị của một kiểu số nguyên khác với bool, char16_t, char32_t, hoặc wchar_t có xếp hạng chuyển đổi số nguyên (4.13) nhỏ hơn xếp hạng int có thể được chuyển đổi thành giá trị pr của kiểu int nếu int có thể biểu diễn tất cả các giá trị của loại nguồn; nếu không, giá trị prvalue nguồn có thể được chuyển đổi thành một giá trị prvalue của kiểu unsigned int.

Trong khi chuyển đổi unsigned char để char không được phân loại như xúc tiến vì cấp bậc của họ là giống hệt nhau:

(§4.13/1) [...] Xếp hạng của char sẽ tương đương với cấp bậc ký char và unsigned char. [...]

Nó được phân loại như chuyển đổi không thể thiếu (§4.7) thay vào đó, và, như mô tả ở trên, chương trình khuyến mãi được ưa thích hơn chuyển đổi trong nghị quyết tình trạng quá tải.

3

Trong tiêu chuẩn C++, char không được xác định là chưa ký hoặc được ký (mặc dù kích thước là 1 byte), do đó, việc triển khai được xác định. Vì vậy, trong thực hiện của bạn, tôi tin rằng nó đã ký char đó là lý do tại sao nó được thăng chức.

+0

Điểm tuyệt vời –

Các vấn đề liên quan