2012-05-05 18 views
9

Tôi đã mã sau:Tại sao gcc không cảnh báo khi một giá trị enum hoặc int được truyền vào như đối số của hàm là bool?

typedef enum 
{ 
    FOO, 
    BAR, 
    BAZ 
} foo_t; 

static void afunc(bool is_it_on) 
{ 
    /* do the job */ 
} 

int main(void) 
{ 
    afunc(BAZ); 
    return 0; 
} 

Biên dịch mã này không tạo ra bất kỳ thông điệp cảnh báo, ngay cả với -Wall -Wextra tùy chọn cho trình biên dịch. Tôi thậm chí đã thử với tùy chọn -Wconversion, không có hiệu lực vì boolenum có vẻ có cùng kích thước với g ++. (kích thước của enum loại không được xác định trong đặc điểm kỹ thuật theo như tôi biết)

Tôi đã chải qua sổ tay gcc và không tìm thấy gì về nó.

Câu hỏi:

  • Có cách nào để buộc các trình biên dịch để tạo ra một cảnh báo trong trường hợp như thế này?
  • Hoặc liệu việc truyền ngầm này có hợp pháp theo đặc tả C++ không?

biên dịch mà tôi đang sử dụng: gcc 4.1.2


ngồi biên tập

Kết luận:

Các giải pháp khả thi duy nhất này dường như định nghĩa một kiểu mới để biểu diễn 0 hoặc 1 và sử dụng nó thay vì bool.

Mã này sẽ như thế nào sau, và g ++ phàn nàn về loại chuyển đổi:

typedef enum 
{ 
    FOO1, 
    FOO2 
} foo_t; 

typedef enum 
{ 
    MY_FALSE, 
    MY_TRUE 
} my_bool_t; 

void foo(my_bool_t a) 
{ 
} 

int main(void) 
{ 
    /* 
     * gcc generates an error. 
     * error: cannot convert ‘foo_t’ to ‘my_bool_t’ 
     * for argument ‘1’ to ‘void foo(my_bool_t)’ 
     */ 
    foo(FOO1); 
    return 0; 
} 
+1

Bởi vì C++' loại hệ thống chỉ tốt cho các loại do người dùng định nghĩa, cho các kiểu dựng sẵn mà nó luôn luôn hút. Hậu quả của di sản C của nó. –

+0

Có vẻ như vậy.Tôi đã quyết định gõ một loại mới dành riêng để đại diện cho chỉ 0 hoặc 1, và sử dụng nó thay vì bool mà dường như được dự định để diễn tả _true_ hoặc _false_. – orchistro

Trả lời

10

Vâng, những chuyển đổi tiềm ẩn là hoàn toàn hợp pháp.

C++ 11 dự thảo n3290, §4.12 chuyển đổi Boolean:

Một prvalue của số học, liệt kê unscoped, con trỏ, hoặc con trỏ đến loại thành viên có thể được chuyển đổi sang một prvalue kiểu bool. Một giá trị bằng không, giá trị con trỏ null, hoặc giá trị con trỏ thành viên null được chuyển thành false; bất kỳ giá trị nào khác được chuyển thành true. Giá trị của loại std :: nullptr_t có thể được chuyển đổi thành giá trị của loại bool; giá trị kết quả là sai.

Cảnh báo về các chuyển đổi này (đối với loại số học) có thể dẫn đến một số cảnh báo lớn trên toàn bộ địa điểm, tôi không nghĩ rằng nó có thể quản lý được.

Trong C++ 11, bạn có thể sử dụng scoped enums để ngăn chặn điều đó chuyển đổi ngầm:

này thất bại trong việc biên dịch vì thiếu một sự chuyển đổi từ Foo để bool:

enum class Foo { ONE }; 

void tryit(bool b) { } 

int main() 
{ 
    tryit(Foo::ONE); 
} 
+0

Cảm ơn bạn, Mat. Nếu nó là hợp pháp bởi đặc tả C++, tôi đoán cách duy nhất để đạt được những gì tôi muốn là gõ typedef một kiểu boolean mới chỉ cho dự án để các thành viên của dự án không phạm sai lầm như đoạn mã. – orchistro

+0

Đáng buồn thay, gcc 4.1.2 dường như không hỗ trợ 'enums scums'. Tôi đoán tôi nên nghỉ mát để giải pháp typedef, và nó thực sự hoạt động. Thông thường, bạn không cần điều đó. Nhưng trong một số trường hợp như bạn đang tái cấu trúc mã của người khác, mà không cần kiểm tra kiểu 'nghiêm ngặt' này, bạn sẽ xin lỗi. Có lẽ tôi nên sử dụng lint. – orchistro

+0

@orchistro: Nếu có thể, hãy thử chuyển sang phiên bản mới hơn trên gcc (Tôi biết nó không dễ dàng ...). gcc 4.1.x là một nhánh cũ. –

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