khai này:
enum fruit {
apple,
orange
};
tuyên bố ba điều: một loại gọi là enum fruit
, và hai điều tra viên gọi apple
và orange
.
enum fruit
thực sự là một loại riêng biệt. Nó tương thích với một số loại số nguyên được xác định thực hiện; ví dụ: enum fruit
có thể tương thích với int
, với char
hoặc thậm chí với unsigned long long
nếu triển khai lựa chọn, miễn là loại được chọn có thể đại diện cho tất cả các giá trị.
Các điều tra viên, mặt khác, là hằng số loại int
. Trong thực tế, có một mẹo phổ biến của việc sử dụng một enum
khai trần tuyên bố int
hằng mà không sử dụng tiền xử lý:
enum { MAX = 1000 };
Vâng, đó có nghĩa là hằng số apple
, mặc dù nó đã được công bố như một phần của định nghĩa của enum fruit
, không thực sự thuộc loại enum fruit
. Lý do cho điều này là lịch sử. Và có, nó có lẽ sẽ có ý nghĩa hơn cho các điều tra viên là hằng số của loại.
Trong thực tế, sự mâu thuẫn này hiếm khi quan trọng. Trong hầu hết các ngữ cảnh, các loại rời rạc (tức là, các loại số nguyên và kiểu liệt kê) có thể hoán đổi cho nhau, và chuyển đổi ngầm thường làm đúng.
enum fruit { apple, orange };
enum fruit obj; /* obj is of type enum fruit */
obj = orange; /* orange is of type int; it's
implicitly converted to enum fruit */
if (obj == orange) { /* operands are converted to a common type */
/* ... */
}
Nhưng kết quả là, như bạn đã thấy, trình biên dịch không có khả năng cảnh báo bạn nếu bạn sử dụng một hằng số liên kết với một loại được liệt kê khi bạn có nghĩa là sử dụng một tên khác.
Một cách để có được mạnh mẽ kiểu kiểm tra là để bọc dữ liệu của bạn trong một cấu trúc:
enum fruit { /* ... */ };
enum color { /* ... */ };
struct fruit { enum fruit f; };
struct color { enum color c; };
struct fruit
và struct color
nhiều loại khác nhau và không phù hợp với không chuyển đổi ngầm (hoặc rõ ràng) giữa chúng. Nhược điểm là bạn phải tham khảo rõ ràng thành viên .f
hoặc .c
. (Hầu hết các lập trình viên C chỉ dựa vào khả năng của họ để có được những điều đúng ngay từ đầu - với kết quả hỗn hợp.)
(typedef
không cung cấp cho bạn kiểm tra kiểu mạnh mẽ; bất kể tên, nó tạo bí danh cho hiện tại loại, không phải là một loại mới).
(Các quy tắc trong C++ là một chút khác nhau.)
Tất cả mưa đá của Apple/LLVM. Tôi tin rằng 3 trình biên dịch bao gồm khá nhiều tất cả các hệ điều hành chính (iOS, Android, Microsoft, OSX), nhưng bất kỳ cập nhật thú vị khác được đánh giá cao. Tôi tin rằng một bài viết trước đề cập đến icc, nhưng tôi không có quyền truy cập vào đó. –