2016-08-26 21 views
8

Hãy có một danh sách các giá trị (foo.lst):Tránh dương tính giả cảnh báo -Wswitch

foo, 
bar, 
baz, 

Hãy làm một enum trong số này

enum foo { 
    #include "foo.lst" 
    _foo_length 
}; 

Hãy sử dụng enum rằng trong một switch :

int main(void) { 
    enum foo[_foo_length]; 

    switch(f[0]) { 
    case foo: return 0; 
    case bar: return 0; 
    case baz: return 0; 
    } 

    __builtin_unreachable(); 
} 

(mã này là ngớ ngẩn, nhưng chỉ cần bỏ qua đó)

.210

Vấn đề:
Với -Wswitch (bao gồm trong -Wall), GCC và Clang (và có lẽ những người khác) sẽ cảnh báo:

cảnh báo: giá trị liệt kê '_foo_length' không được xử lý trong chuyển đổi [-Wswitch]

Giải pháp:

  • Vô hiệu hóa -Wno-switch ẩn mà cảnh báo.
    Nhược điểm: chúng tôi mất cảnh báo về bất kỳ lỗi nào khác trong số case bị thiếu trong chuyển đổi.
  • Thêm một trường hợp default: unreachable();.
    Nhược điểm: chúng tôi mất cảnh báo thời gian biên dịch của các trường hợp bị thiếu, có lợi cho sự cố thời gian chạy nếu chúng tôi đã từng gặp phải một trong các trường hợp bị thiếu khi gỡ lỗi.
  • Thay thế giá trị cuối cùng của enum bằng #define _foo_length (baz + 1), làm cho nó không phải là một phần của enum nữa.
    Nhược điểm: yêu cầu xác định phải được cập nhật theo cách thủ công mỗi khi giá trị được thêm vào danh sách. Ai đó sẽ luôn quên, phá vỡ mọi thứ.

Lý tưởng nhất, cần có một cách để đánh dấu giá trị của một enum như không được chuyển nhượng, do đó làm cho nó không tạo ra một cảnh báo trong trình biên dịch khi đọc các giá trị có thể và điều này là không có, mà không đòi hỏi một macro tiền xử lý cần sửa đổi trùng lặp.

Có điều gì giống như vậy không? Bất kỳ lựa chọn nào khác mà tôi không nghĩ đến?

+0

Vì bạn đang tạo enum động, làm thế nào bạn có thể chắc chắn rằng 'switch' thực sự bao gồm tất cả các trường hợp? – Barmar

+0

Và điều gì sẽ xảy ra nếu tệp không có một trong các trường hợp? Toàn bộ điều này có mùi với tôi. – Barmar

+2

Bạn có thể thêm 'trường hợp _foo_length:' – Barmar

Trả lời

2

Sử dụng

case _foo_length: 
    unreachable(); 
    break; 

sao cho tất cả các trường hợp sẽ bị xử lý. Bạn có thể tạo một macro cho nó để giữ cho nó không bị chi tiết.

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