Berapa ukuran enum dalam C?

140

Saya membuat satu set nilai enum, tetapi saya membutuhkan masing-masing nilai enum selebar 64 bit. Jika saya ingat dengan benar, enum umumnya berukuran sama dengan int; tapi saya pikir saya membaca di suatu tempat bahwa (setidaknya di GCC) kompiler dapat membuat enum lebar yang mereka butuhkan untuk memegang nilai-nilai mereka. Jadi, apakah mungkin untuk memiliki enum yang lebar 64 bit?

mipadi
sumber
1
Jadi jika saya mengerti dengan baik, 2 ^ 32 enum tidak cukup untuk Anda? Atau apakah ini masalah keselarasan, mengapa Anda membutuhkan mereka yang berusia 64 dan bukannya 32, saya sangat ingin tahu.
jokoon
1
@jokoon: Sejujurnya aku tidak ingat lagi. Saya pikir saya ingin enums mengandung nilai yang lebih besar dari 2 ^ 32-1.
mipadi
Satu penggunaan akan jika Anda membutuhkan penyatuan antara enum dan pointer.
Demi

Jawaban:

97

An enumhanya dijamin cukup besar untuk menampung intnilai. Kompiler bebas memilih tipe aktual yang digunakan berdasarkan konstanta enumerasi yang ditentukan sehingga dapat memilih tipe yang lebih kecil jika dapat mewakili nilai yang Anda tetapkan. Jika Anda membutuhkan konstanta enumerasi yang tidak sesuai dengan intAnda, Anda perlu menggunakan ekstensi khusus kompiler untuk melakukannya.

Robert Gamble
sumber
12
Kalimat pertama Anda tampaknya bertentangan dengan kalimat terakhir Anda. Apakah kendala bahwa enumharus lebih besar dari intatau lebih kecil? Mengikuti jawaban @MichaelStum, kalimat pertama Anda seharusnya "Sebuah enumhanya dijamin sesuai dengan intnilai."
HaskellElephant
Sebagai hack sensitif implementasi jelek pada dua platform komplemen (apakah semua sistem saat ini?), Anda dapat memaksa enum menjadi sebesar int dengan memastikannya berisi nilai negatif. Namun bukan teknik yang direkomendasikan.
Persiflage
7
Jawaban ini tampaknya menunjukkan bahwa enum adalah sebesar int. Jawaban Michael Stum , yang merujuk C99, mengatakan bahwa enum mungkin sekecil a char.
Frank Kusters
3
Kalimat pertama dari jawaban ini salah. The enumhanya dijamin akan cukup besar untuk menampung nilai pencacah terbesar di enum.
MM
91

Diambil dari Standar C saat ini (C99): http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1256.pdf

6.7.2.2 Penentu enumerasi
[...]
Kendala
Ekspresi yang mendefinisikan nilai konstanta enumerasi harus berupa ekspresi konstanta integer yang memiliki nilai yang dapat dinyatakan sebagai int.
[...]
Setiap tipe yang disebutkan harus kompatibel dengan char, tipe integer yang ditandatangani, atau tipe integer yang tidak ditandatangani. Pilihan jenis ditentukan oleh implementasi, tetapi harus mampu mewakili nilai-nilai semua anggota enumerasi.

Bukan berarti kompiler pandai mengikuti standar, tetapi pada dasarnya: Jika enum Anda memegang sesuatu selain int, Anda berada dalam "perilaku yang tidak didukung yang mungkin kembali menggigit Anda dalam satu atau dua tahun" wilayah.

Michael Stum
sumber
3
hanya memiliki itu, berikut ini sah menurut saya: enum {LAST = INT_MAX, LAST1, LAST2}; jadi LAST2 tidak dapat diwakili di int, tetapi tidak ada ekspresi yang mendefinisikannya.
Johannes Schaub - litb
4
Dalam PDF yang sebenarnya itu mendefinisikan bahwa: "Identifier dalam daftar enumerator dinyatakan sebagai konstanta yang memiliki tipe int [...]". Saya telah menghilangkannya agar tidak terlalu bertele-tele.
Michael Stum
2
Catatan " sebuah tipe integer ditandatangani, atau suatu tipe integer unsigned". Belum tentu int. shortdan longjuga tipe integer, dan apa pun implementasi yang dipilih, semua nilai harus cocok (" harus mampu mewakili nilai semua anggota enumerasi").
3
Catatan: konstanta enumerasi dan tipe enumerasi bukanlah hal yang sama . Yang pertama adalah isi dari daftar pernyataan enum, yang terakhir adalah variabel aktual. Jadi sementara konstanta enumerasi harus int, variabel enumerasi yang sebenarnya bisa menjadi tipe lain. Ini adalah inkonsistensi yang terkenal dalam standar.
Lundin
1
Untuk memperjelas poin Lundin: For enum my_enum { my_value }, my_valueakan memiliki tipe int, tetapi enum my_enumdapat memiliki tipe implementasi yang ditetapkan yang setidaknya harus mewakili semua nilai enumerasi. Jadi my_valuemungkin ada konversi yang menyempit enum my_enum, tetapi dijamin tidak meluap.
P O'Conbhui
17

Sementara jawaban sebelumnya benar, beberapa kompiler memiliki opsi untuk memecah standar dan menggunakan tipe terkecil yang akan berisi semua nilai.

Contoh dengan GCC (dokumentasi dalam Manual GCC ):

enum ord {
    FIRST = 1,
    SECOND,
    THIRD
} __attribute__ ((__packed__));
STATIC_ASSERT( sizeof(enum ord) == 1 )
Kevin Cox
sumber
11
Sebenarnya, sejauh yang saya bisa lihat ini tidak melanggar standar. Seperti yang dijelaskan dalam jawaban Michael Stum, standar memungkinkan kompiler untuk memilih jenis enum yang sebenarnya, selama semua nilai sesuai.
sleske
2
Saya telah bekerja dengan kompiler MacOS C ++ yang mengeksploitasi rentang nilai terbatas dalam enum untuk menyimpannya dalam tipe yang lebih kecil. Tidak ingat apakah itu Metrowerks Codewarrior atau XCode. Ini dalam standar C ++. Anda tidak dapat mengasumsikan sizeof (MyEnum) == sizeof (int) secara umum.
Persiflage
0

Cukup atur nilai terakhir dari enum ke nilai yang cukup besar untuk menjadikannya ukuran yang Anda inginkan dari enum, maka ukurannya harus sebesar itu:

enum value{a=0,b,c,d,e,f,g,h,i,j,l,m,n,last=0xFFFFFFFFFFFFFFFF};
skirdan
sumber
1
Sementara kode ini dapat menjawab pertanyaan, memberikan konteks tambahan tentang bagaimana dan / atau mengapa memecahkan masalah akan meningkatkan nilai jangka panjang jawaban.
leopal
-1

Kami tidak memiliki kendali atas ukuran suatu enumvariabel. Ini benar-benar tergantung pada implementasinya, dan kompiler memberikan opsi untuk menyimpan nama untuk integer menggunakan enum, demikian enumjuga mengikuti ukuran integer.

Mehul patel
sumber
-1

Dalam bahasa C, suatu enumukuran dijamin dari suatu int. Ada opsi waktu kompilasi ( -fshort-enums) untuk membuatnya singkat (Ini terutama berguna jika nilainya tidak lebih dari 64K). Tidak ada opsi waktu kompilasi untuk meningkatkan ukurannya menjadi 64 bit.

rashok
sumber
-6

Pertimbangkan kode ini:

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

Ini akan memberikan 4 sebagai output. Jadi, berapa pun jumlah elemen dan isi enum, ukurannya selalu tetap.

tushan
sumber
6
Jawaban Michael Stum benar. Ini adalah kompiler khusus. Anda dapat mencobanya sendiri dengan IAR EWARM. IAR EWARM menunjukkan 1 sebagai contoh Anda. Jika ada hingga 255 item itu masih menunjukkan 1. Setelah menambahkan item 256 itu naik ke 2.
desowin
11
Pertanyaannya bukan tentang C ++.
Michas
4
hal-hal penting untuk disadari sebelum menulis lagi C atau C ++: Hanya karena mengkompilasi tidak berarti itu legal menurut Standar. Hanya karena Anda mendapatkan hasil yang diberikan tidak berarti Standar mengatakan bahwa Anda akan selalu atau bahwa pengguna lain akan melakukannya ketika mereka menjalankan kode Anda. Pertanyaan seperti ini membutuhkan jawaban yang merujuk pada Standar atau setidaknya spesifikasi yang ditentukan implementasi untuk kompiler / ABI yang diberikan. Cukup dengan mengkompilasi dan menjalankan program dan melihat satu hasil pada suatu hari tidak ada pelajaran tentang pertanyaan semacam itu (dan sangat sedikit tentang hal lain).
underscore_d