Trong trường hợp đầu tiên, bản thân trình biên dịch đang cố gắng chọn một số nguyên đang gây tràn, và do đó cảnh báo bạn. Nó có khả năng sản xuất INT_MIN
. Chuẩn cho phép bất kỳ giá trị nào trong một signed int
là hằng số enum (xem dưới).
Trong giây, biểu thức (INT_MAX + 1)
được tính trước khi được gán cho out_2
. Một tràn trong biểu thức ở đây là tạo ra một kết quả được cho phép, nhưng đây là hành vi không xác định. Kết quả hợp lệ sau đó được lưu trữ trong enum, đó là lý do tại sao lỗi đầu tiên không được tạo ra.
kêu vang (3.2) cũng sẽ không cảnh báo về vấn đề này, đó là một cách hiệu quả giống hệt nhau:
int a = INT_MAX + 1;
Trong khía cạnh này, kêu vang là không hành xử theo tiêu chuẩn C, vì đây là không xác định.
Kết quả từ gcc so nên sự khác biệt hoàn toàn rõ ràng:
In function ‘main’:
9:9: error: overflow in enumeration values
13:25: warning: integer overflow in expression [-Woverflow]
Trình biên dịch Intel bỏ qua tràn enum, nhưng cảnh báo về sự tràn số nguyên:
enum.c(13): warning #61: integer operation result is out of range
out_2 = INT_MAX + 1
^
Để tham khảo, từ tiêu chuẩn C99 6.7.7.2.2, "Biểu thức xác định giá trị của hằng số liệt kê phải là một biểu thức hằng số nguyên có giá trị biểu thị là
int
; .3," T người nhận dạng trong danh sách liệt kê được khai báo là hằng số có loại
int
và có thể xuất hiện ở bất kỳ nơi nào được phép. "tức là hằng số enum có thể là bất kỳ giá trị
int
nào và có loại
int
. Loại kết quả của biến số enum được xác định có thể là
char
,
int
hoặc
unsigned int
, miễn là nó cho phép tất cả các hằng số có thể có trong enum. Như vậy cả hai
enums
trong ví dụ là không xác định, vì cả hai đều yêu cầu tràn số nguyên. Đầu tiên là bất hợp pháp một cách rõ ràng.
Khá chắc chắn tiêu chuẩn không xác định phạm vi 'enum'. – asveikau
Đoán của tôi: nó đánh giá INT_MAX + 1 trước tiên, nó sẽ bao quanh và gán nó cho out_2. –
@ johnny: không, nó gọi UB. –