Kích thước của một enum trong C là gì?


140

Tôi đang tạo một tập hợp các giá trị enum, nhưng tôi cần mỗi giá trị enum rộng 64 bit. Nếu tôi nhớ lại một cách chính xác, một enum thường có cùng kích thước với một int; nhưng tôi nghĩ rằng tôi đã đọc ở đâu đó rằng (ít nhất là trong GCC) trình biên dịch có thể tạo ra enum bất kỳ chiều rộng nào họ cần để giữ các giá trị của chúng. Vì vậy, có thể có một enum rộng 64 bit không?


1
Vì vậy, nếu tôi hiểu rõ, 2 ^ 32 enums không đủ cho bạn? Hoặc đó là một mối quan tâm sắp xếp, tại sao bạn cần những người đó là 64 thay vì 32, tôi rất tò mò.
jokoon

1
@jokoon: Thật lòng tôi không nhớ nữa. Tôi nghĩ rằng tôi muốn các enum chứa các giá trị lớn hơn 2 ^ 32-1.
mipadi

Một lần sử dụng sẽ là nếu bạn cần một sự kết hợp giữa enum và một con trỏ.
Demi

Câu trả lời:


97

An enumchỉ được đảm bảo đủ lớn để giữ intcác giá trị. Trình biên dịch có thể tự do chọn loại thực tế được sử dụng dựa trên các hằng số liệt kê được xác định để nó có thể chọn loại nhỏ hơn nếu nó có thể đại diện cho các giá trị bạn xác định. Nếu bạn cần các hằng số liệt kê không phù hợp với một, intbạn sẽ cần sử dụng các phần mở rộng dành riêng cho trình biên dịch để làm như vậy.


12
Câu đầu tiên của bạn dường như mâu thuẫn với câu cuối của bạn. Là ràng buộc mà một enumnên lớn hơn một inthoặc nhỏ hơn? Theo câu trả lời của @MichaelStum, câu đầu tiên của bạn phải là "An enumchỉ được đảm bảo phù hợp với intgiá trị".
HaskellElephant

Là một hack nhạy cảm khi thực hiện trên các nền tảng bổ sung twos (có phải tất cả các hệ thống hiện nay không?), Bạn có thể buộc một enum phải lớn bằng int bằng cách đảm bảo nó chứa các giá trị âm. Không phải là một kỹ thuật được đề nghị mặc dù.
thuyết phục

7
Câu trả lời này dường như gợi ý rằng một enum lớn như một int. Câu trả lời của Michael Stum , tham chiếu đến C99, nói rằng một enum có thể nhỏ như a char.
Frank Kuster

3
Câu đầu tiên của câu trả lời này là không chính xác. Điều enumnày chỉ được đảm bảo đủ lớn để giữ giá trị của điều tra viên lớn nhất trong enum.
MM

91

Lấy từ Tiêu chuẩn C hiện tại (C99): http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1256.pdf

6.7.2.2 Các chỉ định liệt kê
[...]
Các ràng buộc
Biểu thức xác định giá trị của hằng số liệt kê sẽ là một biểu thức hằng số nguyên có giá trị biểu thị dưới dạng int.
[...]
Mỗi loại liệt kê sẽ tương thích với char, loại số nguyên đã ký hoặc loại số nguyên không dấu. Sự lựa chọn của loại được xác định theo thực hiện, nhưng sẽ có khả năng đại diện cho các giá trị của tất cả các thành viên của bảng liệt kê.

Không phải trình biên dịch nào cũng tuân theo tiêu chuẩn, nhưng về cơ bản: Nếu enum của bạn giữ bất cứ thứ gì khác ngoài int, bạn đang ở trong "hành vi không được hỗ trợ sâu sắc có thể quay lại cắn bạn trong một hoặc hai năm" lãnh thổ.


3
chỉ có điều đó, những điều sau đây là hợp lệ tôi nghĩ: enum {LAST = INT_MAX, LAST1, LAST2}; vì vậy LAST2 không thể biểu diễn trong int, nhưng không có biểu thức xác định nó.
Julian Schaub - litb

4
Trong bản PDF thực tế, nó xác định rằng: "Các định danh trong danh sách liệt kê được khai báo là hằng số có kiểu int [...]". Tôi đã bỏ qua điều đó để làm cho nó không quá dài dòng.
Michael Stum

2
Lưu ý " một loại nguyên ký, hoặc một kiểu dữ liệu integer unsigned". Không nhất thiết int. shortlongcũng là các kiểu số nguyên và bất kể lựa chọn triển khai nào, tất cả các giá trị phải phù hợp (" sẽ có khả năng đại diện cho các giá trị của tất cả các thành viên của bảng liệt kê").

3
Đáng chú ý: kiểu liệt kê hằngkiểu liệt kê không giống nhau . Cái trước là nội dung của danh sách khai báo enum, cái sau là biến thực tế. Vì vậy, trong khi các hằng số liệt kê phải là int, biến liệt kê thực tế có thể là một loại khác. Đây là một sự không nhất quán nổi tiếng trong tiêu chuẩn.
Lundin

1
Để làm rõ quan điểm của Lundin: For enum my_enum { my_value }, my_valuesẽ có loại int, nhưng enum my_enumcó thể có loại được xác định thực hiện, ít nhất phải đại diện cho tất cả các giá trị liệt kê. Vì vậy, my_valuecó thể có một chuyển đổi thu hẹp thành enum my_enum, nhưng nó được đảm bảo không tràn.
P O'Conbhui

17

Trong khi các câu trả lời trước là chính xác, một số trình biên dịch có các tùy chọn để phá vỡ tiêu chuẩn và sử dụng loại nhỏ nhất sẽ chứa tất cả các giá trị.

Ví dụ với GCC (tài liệu trong Hướng dẫn sử dụng GCC ):

enum ord {
    FIRST = 1,
    SECOND,
    THIRD
} __attribute__ ((__packed__));
STATIC_ASSERT( sizeof(enum ord) == 1 )

11
Trên thực tế, theo như tôi có thể thấy điều này không phá vỡ tiêu chuẩn. Như đã giải thích trong câu trả lời của Michael Stum, tiêu chuẩn cho phép trình biên dịch chọn loại enum thực tế, miễn là tất cả các giá trị phù hợp.
sleske

2
Tôi đã làm việc với các trình biên dịch MacOS C ++ khai thác phạm vi giá trị giới hạn trong một enum để lưu trữ chúng trong các loại nhỏ hơn. Không thể nhớ nếu đó là Metrowerks Codewar Warrior hoặc XCode. Đây là trong tiêu chuẩn C ++. Bạn không thể giả sử sizeof (MyEnum) == sizeof (int) nói chung.
thuyết phục

0

Chỉ cần đặt giá trị cuối cùng của enum thành một giá trị đủ lớn để làm cho nó có kích thước bạn muốn là enum, thì nó phải là kích thước đó:

enum value{a=0,b,c,d,e,f,g,h,i,j,l,m,n,last=0xFFFFFFFFFFFFFFFF};

1
Mặc dù mã này có thể trả lời câu hỏi, việc cung cấp ngữ cảnh bổ sung về cách thức và / hoặc lý do giải quyết vấn đề sẽ cải thiện giá trị lâu dài của câu trả lời.
leopal

-1

Chúng tôi không kiểm soát kích thước của một enumbiến. Nó hoàn toàn phụ thuộc vào việc triển khai và trình biên dịch cung cấp tùy chọn lưu trữ tên cho một số nguyên bằng cách sử dụng enum, do đó, enumtheo kích thước của một số nguyên.


-1

Trong ngôn ngữ C, một enumđược đảm bảo có kích thước của một int. Có một tùy chọn thời gian biên dịch ( -fshort-enums) để làm cho nó ngắn (Điều này chủ yếu hữu ích trong trường hợp các giá trị không quá 64K). Không có tùy chọn thời gian biên dịch để tăng kích thước của nó lên 64 bit.


-6

Xem xét mã này:

enum value{a,b,c,d,e,f,g,h,i,j,l,m,n};
value s;
cout << sizeof(s) << endl;

Nó sẽ cho 4 là đầu ra. Vì vậy, bất kể số lượng phần tử enumchứa, kích thước của nó luôn luôn cố định.


6
Câu trả lời của Michael Stum là chính xác. Đây là trình biên dịch cụ thể. Bạn có thể tự mình thử với IAR EWARM. IAR EWARM hiển thị 1 cho ví dụ của bạn. Nếu có tới 255 mục, nó vẫn hiển thị 1. Sau khi thêm mục thứ 256, nó sẽ tăng lên 2.
desowin

10
Câu hỏi không phải là về C ++.
Michas

3
những điều quan trọng cần nhận ra trước khi viết thêm C hoặc C ++: Chỉ vì nó biên dịch không có nghĩa là nó hợp pháp theo Tiêu chuẩn. Chỉ vì bạn nhận được một kết quả nhất định không có nghĩa là Tiêu chuẩn nói rằng bạn sẽ luôn luôn hoặc những người dùng khác sẽ làm khi họ chạy mã của bạn. Các câu hỏi như thế này cần một câu trả lời tham chiếu Tiêu chuẩn hoặc ít nhất là thông số kỹ thuật được xác định thực hiện cho trình biên dịch / ABI đã cho. Đơn giản chỉ cần biên dịch và chạy một chương trình và thấy một kết quả trong một ngày sẽ không có bài học nào về những câu hỏi như vậy (và rất ít về bất cứ điều gì khác).
gạch dưới
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.