ขนาดของ enum ใน C คืออะไร?


140

ฉันกำลังสร้างชุดค่า enum แต่ฉันต้องการค่า enum แต่ละตัวที่มีความกว้าง 64 บิต ถ้าฉันจำได้อย่างถูกต้องโดยทั่วไป Enum จะมีขนาดเท่ากันกับ int แต่ฉันคิดว่าฉันอ่านที่ไหนสักแห่ง (อย่างน้อยใน GCC) คอมไพเลอร์สามารถทำให้ enum ความกว้างใด ๆ ที่พวกเขาต้องการเพื่อรักษาค่าของพวกเขา เป็นไปได้ไหมที่จะมี enum ที่กว้าง 64 บิต?


1
ดังนั้นถ้าฉันเข้าใจดี 2 ^ 32 enums ไม่เพียงพอสำหรับคุณ หรือเป็นข้อกังวลเกี่ยวกับการจัดตำแหน่งทำไมคุณถึงต้องการให้ 64 เป็น 32 แทนฉันอยากรู้มาก
jokoon

1
@ jokoon: ฉันจำไม่ได้อีกแล้ว ฉันคิดว่าฉันต้องการให้ enums มีค่ามากกว่า 2 ^ 32-1
mipadi

การใช้งานครั้งเดียวจะเป็นถ้าคุณต้องการการรวมกันระหว่าง enum และตัวชี้
Demi

คำตอบ:


97

enumมีการประกันเท่านั้นที่จะมีขนาดใหญ่พอที่จะถือintค่า คอมไพเลอร์มีอิสระในการเลือกประเภทที่แท้จริงที่ใช้ตามค่าคงที่การแจงนับที่กำหนดไว้เพื่อให้สามารถเลือกประเภทที่เล็กลงหากสามารถแสดงค่าที่คุณกำหนดได้ หากคุณต้องการค่าคงที่การแจงนับที่ไม่พอดีintคุณจะต้องใช้ส่วนขยายเฉพาะสำหรับคอมไพเลอร์


12
ประโยคแรกของคุณดูเหมือนจะขัดแย้งกับครั้งสุดท้ายของคุณ ข้อ จำกัด ที่enumควรจะใหญ่กว่าintหรือเล็กกว่านั้นคืออะไร? การปฏิบัติตามคำตอบของ @MichaelStum ประโยคแรกของคุณควรเป็น " enumรับประกันได้เพียงค่าเดียวเท่านั้นint"
HaskellElephant

ในฐานะที่เป็นแฮ็คที่มีความอ่อนไหวในการติดตั้งใช้งานบนแพลตฟอร์มเสริมสองครั้ง (นั่นคือทุกระบบในปัจจุบันหรือไม่) คุณสามารถบังคับให้ enum มีขนาดใหญ่เท่ากับ int โดยทำให้แน่ใจว่ามีค่าลบ ไม่ใช่เทคนิคที่แนะนำ
persiflage

7
คำตอบนี้ดูเหมือนว่าจะแนะนำว่า enum intมีขนาดใหญ่เป็น คำตอบไมเคิล Stum ของซึ่งอ้างอิง C99 กล่าวว่า Enum charที่อาจจะมีขนาดเล็กเป็น
Frank Kusters

3
ประโยคแรกของคำตอบนี้ไม่ถูกต้อง การenumรับประกันจะมีขนาดใหญ่พอที่จะเก็บค่าของตัวแจงนับที่ใหญ่ที่สุดใน enum
MM

91

นำมาจากมาตรฐาน C ปัจจุบัน (C99): http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1256.pdf

6.7.2.2 ตัวระบุการแจกแจง
[... ]
ข้อ จำกัด
นิพจน์ที่กำหนดค่าของค่าคงที่การแจงนับจะต้องเป็นนิพจน์ค่าคงที่จำนวนเต็มซึ่งมีค่าที่สามารถแทนค่าได้เป็น int
[... ]
แต่ละประเภทที่แจกแจงต้องเข้ากันได้กับถ่านประเภทจำนวนเต็มที่ลงนามหรือประเภทจำนวนเต็มไม่ได้ลงนาม ตัวเลือกของประเภทคือกำหนดการนำไปใช้ แต่จะต้องสามารถแสดงค่าของสมาชิกทั้งหมดของการแจงนับ

ไม่ว่าคอมไพเลอร์จะเก่งในการทำตามมาตรฐาน แต่โดยพื้นฐานแล้ว: หาก enum ของคุณมีสิ่งอื่นนอกเหนือจาก int คุณจะอยู่ใน "พฤติกรรมที่ไม่ได้รับการสนับสนุนที่ลึกล้ำซึ่งอาจกลับมากัดคุณได้ภายในหนึ่งปี


3
มีเพียงสิ่งต่อไปนี้ที่ถูกต้องฉันคิดว่า: enum {LAST = INT_MAX, LAST1, LAST2}; ดังนั้น LAST2 จึงไม่สามารถแทนค่าได้ใน int แต่ไม่มีนิพจน์ที่กำหนด
Johannes Schaub - litb

4
ใน PDF จริงกำหนดว่า: "ตัวระบุในรายการตัวแจงนับเป็นค่าคงที่ที่มีประเภท int [... ]" ฉันไม่ได้ตั้งใจที่จะทำให้มันไม่ verbose เกินไป
Michael Stum

2
หมายเหตุ " ชนิดจำนวนเต็มลงนามหรือชนิดจำนวนเต็มไม่ได้ลงนาม" ไม่จำเป็นต้องเป็น และเป็นประเภทจำนวนเต็มด้วยเช่นกันและไม่ว่าการดำเนินการใดจะเลือกค่าทั้งหมดต้องพอดี (" จะต้องสามารถแสดงค่าของสมาชิกทั้งหมดของการแจงนับ") intshortlong

3
เด่น: คงแจงนับและระบุชนิด ไม่ได้เป็นสิ่งเดียวกัน อดีตเป็นเนื้อหาของรายการประกาศ enum หลังเป็นตัวแปรจริง ดังนั้นในขณะที่ค่าคงที่การแจงนับต้องเป็นintตัวแปรการแจงนับที่แท้จริงอาจเป็นประเภทอื่น นี่คือความไม่สอดคล้องกันที่รู้จักกันดีในมาตรฐาน
Lundin

1
เพื่อชี้แจงจุด Lundin ของ: สำหรับenum my_enum { my_value }, my_valueจะมีประเภทintแต่enum my_enumสามารถมีประเภทที่กำหนดไว้ในการนำไปปฏิบัติซึ่งอย่างน้อยจะต้องแสดงค่าการแจงนับ ดังนั้นmy_valueอาจมีการแปลงให้แคบลงenum my_enumแต่รับประกันได้ว่าจะไม่ล้น
P O'Conbhui

17

ในขณะที่คำตอบก่อนหน้านี้ถูกต้องคอมไพเลอร์บางตัวมีตัวเลือกในการทำลายมาตรฐานและใช้ประเภทที่เล็กที่สุดที่จะมีค่าทั้งหมด

ตัวอย่างกับGCC (เอกสารในคู่มือ GCC ):

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

11
ที่จริงเท่าที่ฉันเห็นสิ่งนี้ไม่ได้ทำลายมาตรฐาน ตามที่อธิบายไว้ในคำตอบของ Michael Stum มาตรฐานอนุญาตให้คอมไพเลอร์เลือกชนิดของ enums จริงตราบเท่าที่ค่าทั้งหมดเหมาะสม
sleske

2
ฉันได้ทำงานกับคอมไพเลอร์ MacOS C ++ ที่ใช้ประโยชน์จากช่วงค่าที่ จำกัด ใน enum เพื่อเก็บไว้ในประเภทที่เล็กลง จำไม่ได้ว่าเป็น Metrowerks Codewarrior หรือ XCode สิ่งนี้อยู่ในมาตรฐาน C ++ คุณไม่สามารถถือว่า sizeof (MyEnum) == sizeof (int) โดยทั่วไป
persiflage

0

เพียงตั้งค่าสุดท้ายของ enum เป็นค่าที่มีขนาดใหญ่พอที่จะทำให้เป็นขนาดที่คุณต้องการให้ enum เป็นขนาดนั้นก็ควรเป็นขนาดนั้น:

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

2
ในขณะที่รหัสนี้อาจตอบคำถามให้บริบทเพิ่มเติมเกี่ยวกับวิธีการและ / หรือทำไมมันแก้ปัญหาจะปรับปรุงค่าระยะยาวของคำตอบ
leopal

-1

เราไม่สามารถควบคุมขนาดของenumตัวแปรได้ มันขึ้นอยู่กับการดำเนินการทั้งหมดและคอมไพเลอร์ให้ตัวเลือกในการจัดเก็บชื่อสำหรับจำนวนเต็มโดยใช้enumดังนั้นจึงenumเป็นไปตามขนาดของจำนวนเต็ม


-1

ในภาษา C การรับประกันได้ว่าจะมีขนาดของenum intมีตัวเลือกเวลาในการคอมไพล์ ( -fshort-enums) เพื่อทำให้สั้น (ซึ่งมีประโยชน์เป็นหลักในกรณีที่ค่าไม่เกิน 64K) ไม่มีตัวเลือกเวลารวบรวมเพื่อเพิ่มขนาดเป็น 64 บิต


-6

พิจารณารหัสนี้:

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

มันจะให้ 4 เป็นเอาท์พุท ดังนั้นไม่ว่าจะมีองค์ประกอบจำนวนenumเท่าใดก็ตามขนาดของมันก็จะคงที่เสมอ


6
คำตอบของ Michael Stum นั้นถูกต้อง นี่เป็นคอมไพเลอร์เฉพาะ คุณสามารถลองด้วยตัวคุณเองด้วย IAR EWARM IAR EWARM แสดง 1 สำหรับตัวอย่างของคุณ หากมีมากถึง 255 รายการก็ยังคงแสดง 1 หลังจากเพิ่มรายการที่ 256 มันจะสูงถึง 2
desowin

11
คำถามไม่เกี่ยวกับ C ++
Michas

4
สิ่งสำคัญที่ต้องรู้ก่อนที่จะเขียน C หรือ C ++ อีกต่อไป: เพียงเพราะการรวบรวมไม่ได้หมายความว่ามันถูกกฎหมายตามมาตรฐาน เพียงเพราะคุณได้รับผลลัพธ์ที่กำหนดไม่ได้หมายความว่า Standard บอกว่าคุณจะทำตลอดเวลาหรือผู้ใช้รายอื่นจะทำเมื่อพวกเขาเรียกใช้รหัสของคุณ คำถามเช่นนี้ต้องการคำตอบที่อ้างอิงถึงมาตรฐานหรืออย่างน้อยข้อกำหนดที่กำหนดโดยการนำไปปฏิบัติสำหรับคอมไพเลอร์ / ABI ที่กำหนด เพียงรวบรวมและเรียกใช้โปรแกรมและเห็นผลลัพธ์หนึ่งรายการในหนึ่งวันไม่มีบทเรียนเกี่ยวกับคำถามดังกล่าว (และมีอะไรน้อยมากเกี่ยวกับสิ่งอื่น)
underscore_d
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.