วิธีกำหนดประเภท enum (enum) ใน C เป็นอย่างไร


272

ฉันไม่แน่ใจว่าเป็นไวยากรณ์ที่เหมาะสมสำหรับการใช้ C enums อะไร ฉันมีรหัสต่อไปนี้:

enum {RANDOM, IMMEDIATE, SEARCH} strategy;
strategy = IMMEDIATE;

แต่สิ่งนี้ไม่ได้คอมไพล์ด้วยข้อผิดพลาดต่อไปนี้:

error: conflicting types for strategy
error: previous declaration of strategy was here

ผมทำอะไรผิดหรือเปล่า?


7
คำถามอายุหลายปีคงไม่มีใครเห็นสิ่งนี้ แต่ทำไมถึงเกิดข้อผิดพลาด? มันควรจะทำงานได้อย่างสมบูรณ์แบบเหมือนอยู่ในคำถามเท่าที่ความรู้ของฉันไป
Utkan Gezer

2
@Solver ทำไมไวยากรณ์นี้ผิด
MCG

6
@MCQ การลบ necro'd necro: ไวยากรณ์ที่แสดงในคำถามนั้นไม่ผิดใน C. มันประกาศstrategyว่ามีประเภทที่ไม่ระบุชื่อและกำหนดหนึ่งในค่าที่ประกาศไว้ของประเภทนั้น ยิ่งไปกว่านั้นถ้าฉันห่อโค้ดที่แสดงในmain()ฟังก์ชั่นเล็ก ๆ น้อย ๆแล้วมันก็คอมไพล์แล้วสำหรับฉันโดยไม่มีการเตือนด้วย gcc 4.4.7 คำตอบบางคำบอกเป็นนัยเดียวกันแม้ว่าจะไม่ใช่คำพูดมากมาย
John Bollinger

5
คำตอบส่วนใหญ่หายไปจากความจริงที่ว่าโค้ดสองบรรทัดในคำถามไม่ใช่แค่ตัวอย่างเท่านั้น มันเป็นไฟล์ต้นฉบับทั้งหมด หากสองบรรทัดเหล่านั้นรวมอยู่ในเนื้อความของฟังก์ชันจะไม่มีข้อผิดพลาด หากปรากฏที่ขอบเขตไฟล์นอกการประกาศฟังก์ชั่นใด ๆ คุณจะได้รับข้อผิดพลาดที่ OP ถามเกี่ยวกับ (รวมถึงบางอย่างเมื่อฉันลอง) ปัญหาพื้นฐานคือคอมไพเลอร์พยายามที่จะstrategy = IMMEDIATE;ถือเป็นการประกาศ มันมีรูปแบบที่จะถูกกฎหมายใน pre-ANSI C แต่ใน C สมัยใหม่นั้นผิดกฎหมาย ไม่อนุญาตการมอบหมายที่ขอบเขตไฟล์
Keith Thompson

3
@Solver: enum strategy { ... };กำหนดประเภทที่ระบุชื่อenum strategyโดยที่strategyแท็ก enum { ... } strategy;กำหนดที่ไม่ระบุชื่อระบุชนิด (แท็กไม่ได้) และstrategyวัตถุเดียวประเภทนั้นชื่อ ทั้งสองอย่างถูกกฎหมายอย่างสมบูรณ์ พวกเขาหมายถึงสิ่งต่าง ๆ
Keith Thompson

คำตอบ:


377

การประกาศตัวแปร enum ทำได้ดังนี้:

enum strategy {RANDOM, IMMEDIATE, SEARCH};
enum strategy my_strategy = IMMEDIATE;

อย่างไรก็ตามคุณสามารถใช้ a typedefเพื่อย่อการประกาศตัวแปรให้สั้นลงดังนี้:

typedef enum {RANDOM, IMMEDIATE, SEARCH} strategy;
strategy my_strategy = IMMEDIATE;

มีแบบแผนการตั้งชื่อเพื่อแยกความแตกต่างระหว่างชนิดและตัวแปรเป็นความคิดที่ดี:

typedef enum {RANDOM, IMMEDIATE, SEARCH} strategy_type;
strategy_type my_strategy = IMMEDIATE;

1
แต่ OP ต้องการตัวแปรประเภท enum นิรนาม
osvein

ฉันไม่สามารถพิมพ์enum MyEnum {} myVar;แล้วใช้ตัวแปรmyVarดังนี้:myVar = SOMEENUMCONSTANT;
Mushy

451

มันคุ้มค่าที่ชี้ให้เห็นว่าคุณไม่จำเป็นต้อง typedefคุณสามารถทำมันได้ดังต่อไปนี้

enum strategy { RANDOM, IMMEDIATE, SEARCH };
enum strategy my_strategy = IMMEDIATE;

typedefมันเป็นคำถามที่รูปแบบไม่ว่าจะเป็นคุณต้องการ enum strategyโดยไม่ได้ถ้าคุณต้องการที่จะอ้างถึงประเภทการแจงนับที่คุณจำเป็นต้องใช้ ด้วยคุณสามารถพูดstrategyได้

ทั้งสองมีข้อดีและข้อเสียของพวกเขา สิ่งหนึ่งนั้นมีประโยชน์มากกว่า แต่เก็บตัวระบุประเภทไว้ในแท็ก - เนมสเปซซึ่งพวกมันจะไม่ขัดแย้งกับตัวระบุสามัญ (คิดstruct statและstatฟังก์ชั่น: สิ่งเหล่านี้จะไม่ขัดแย้งกัน) และที่คุณเห็นทันทีว่าเป็นประเภท อีกอันหนึ่งสั้นกว่า แต่นำตัวระบุชนิดมาไว้ในเนมสเปซปกติ


6
มันไม่ควรเป็นคำตอบที่ยอมรับได้เพราะมันผิด คุณไม่สามารถใช้กลยุทธ์ enum {... }; ใน C - คุณสามารถและควรทำใน C ++
ชัดเจน

19
@Clearer: รหัสนี้ทำงานได้อย่างสมบูรณ์ นี่คือตัวอย่างการทำงาน: ideone.com/T0YV17 โปรดทราบว่ามันใช้enumคำหลักในทั้งสองบรรทัด
RichieHindle

หรือ "กลยุทธ์ typedef enum {RANDOM, IMMEDIATE, SEARCH} strategy_t;" และ dev ที่ใช้ enum สามารถใช้การประชุมที่พวกเขาต้องการ
Andy Nugent

สิ่งนี้ใช้งานได้ดี: enum strategy { RANDOM, IMMEDIATE, SEARCH }; เมื่อคุณต้องการตัวอย่างของ enum นั้น: `กลยุทธ์ enum myEnum;
3629249

2
@AndyNugent อย่าทำอย่างนั้น! * ประเภท _t สงวนไว้โดย POSIX
osvein

58

คุณพยายามที่จะประกาศstrategyสองครั้งและนั่นคือสาเหตุที่คุณได้รับข้อผิดพลาดด้านบน งานดังต่อไปนี้โดยไม่มีการร้องเรียนใด ๆ (รวบรวมด้วยgcc -ansi -pendantic -Wall):

#include <stdio.h>

enum { RANDOM, IMMEDIATE, SEARCH } strategy = IMMEDIATE;

int main(int argc, char** argv){
    printf("strategy: %d\n", strategy);

    return 0;
}

หากแทนที่ข้างต้นบรรทัดที่สองจะเปลี่ยนเป็น:

...
enum { RANDOM, IMMEDIATE, SEARCH } strategy;
strategy = IMMEDIATE;
...

จากคำเตือนคุณสามารถเห็นความผิดพลาดได้ง่าย:

enums.c:5:1: warning: data definition has no type or storage class [enabled by default]
enums.c:5:1: warning: type defaults to int in declaration of strategy [-Wimplicit-int]
enums.c:5:1: error: conflicting types for strategy
enums.c:4:36: note: previous declaration of strategy was here

ดังนั้นคอมไพเลอร์จึงใช้strategy = IMMEDIATEสำหรับการประกาศตัวแปรที่เรียกว่าstrategyชนิดเริ่มต้นintแต่มีการประกาศตัวแปรก่อนหน้านี้ด้วยชื่อนี้แล้ว

อย่างไรก็ตามหากคุณทำการกำหนดในmain()ฟังก์ชั่นมันจะเป็นรหัสที่ถูกต้อง:

#include <stdio.h>

enum { RANDOM, IMMEDIATE, SEARCH } strategy = IMMEDIATE;

int main(int argc, char** argv){
    strategy=SEARCH;
    printf("strategy: %d\n", strategy);

    return 0;
}

48

เมื่อคุณพูด

enum {RANDOM, IMMEDIATE, SEARCH} strategy;

คุณสร้างตัวแปรอินสแตนซ์เดียวที่เรียกว่า 'กลยุทธ์' ของ enum นิรนาม นี่ไม่ใช่สิ่งที่มีประโยชน์มากที่ต้องทำ - คุณต้องมี typedef:

typedef enum {RANDOM, IMMEDIATE, SEARCH} StrategyType; 
StrategyType strategy = IMMEDIATE;

9
ทำไมจึงไม่มีประโยชน์ หากฉันไม่สนใจชื่อของประเภทนั้นทำไมฉันต้องให้ชื่อด้วย สิ่งเดียวที่ตั้งใจไว้คือการตั้งชื่อตัวแปรดังนั้นจึงเป็นไปได้ที่จะกำหนดค่าใหม่ให้กับมัน
MSalters

3
ฉันบอกว่ามันไม่มีประโยชน์มากและฉันไม่เชื่อว่ามันเป็น แน่นอนฉันไม่ได้ใช้รูปแบบนี้ในรหัสของตัวเอง YMMV

3
@HorseSMith Enum ที่ไม่มีชื่อไม่มีประโยชน์มากเพราะคุณไม่สามารถมีตัวแปรอื่น ๆ ของประเภทนั้นหรือพารามิเตอร์ฟังก์ชันหรือค่าส่งคืน ถ้าตัวแปรเดียวคือทั้งหมดที่คุณต้องการมันก็โอเค
Bob Stein

3
บางคนที่ไม่ได้ใช้ enums นิรนามไม่ได้พิสูจน์ว่าพวกเขาไม่มีประโยชน์ คุณไม่จำเป็นต้องพิมพ์ หลักเกณฑ์ของโค้ดบางอย่าง (kernel.org/doc/Documentation/CodingStyle) ไม่แนะนำให้ใช้
martinkunev

2
คำตอบนี้ยังทำให้เข้าใจผิด คำตอบของ Tarc เป็นคำตอบเดียวที่ถูกต้องที่นี่
nightpool

13

ตามที่เขียนไว้ไม่มีอะไรผิดปกติกับรหัสของคุณ คุณแน่ใจหรือว่ายังไม่ได้ทำอะไรบางอย่าง

int strategy;
...
enum {RANDOM, IMMEDIATE, SEARCH} strategy;

ข้อความแสดงข้อผิดพลาดชี้ไปที่บรรทัดใด เมื่อมีข้อความว่า "การประกาศก่อนหน้านี้ของ 'กลยุทธ์' อยู่ที่นี่" อะไรคือ "ที่นี่" และมันแสดงอะไร


6
เขาอาจทำstrategy = IMMEDIATE;ที่ขอบเขตไฟล์ การมอบหมายไม่สามารถเกิดขึ้นได้ที่ขอบเขตไฟล์นอกฟังก์ชั่นทั้งหมด ดังนั้นคอมไพเลอร์พยายามทำสิ่งที่ดีที่สุดจากข้อผิดพลาดและคิดว่าเขาหมายถึงint strategy = IMMEDIATE;ความขัดแย้งเกิดขึ้น ณ จุดนั้น
Johannes Schaub - litb

2
นี่คือคำตอบที่ดีที่สุดมีความสับสนในเยื่อเมือกในคำตอบอื่น ๆ มันเจ็บปวด
คลาย

12

@ThoAppelsin ในความคิดเห็นของเขาเพื่อตอบคำถามถูกต้อง ข้อมูลโค้ดที่โพสต์ในคำถามนั้นถูกต้องและไม่มีข้อผิดพลาด ข้อผิดพลาดที่คุณมีจะต้องเป็นเพราะไวยากรณ์ไม่ดีอื่น ๆ ในสถานที่อื่น ๆ ของไฟล์ต้นฉบับของคุณค enum{a,b,c};กำหนดค่าคงที่สามสัญลักษณ์ ( a, bและc) ซึ่งเป็นจำนวนเต็มมีค่า0, 1และ2ตามลำดับ แต่เมื่อเราใช้enumมันเป็นเพราะเราไม่ได้มักจะดูแลเกี่ยวกับค่าเฉพาะจำนวนเต็มเราดูแลเพิ่มเติมเกี่ยวกับความหมายของชื่อสัญลักษณ์คง หมายความว่าคุณสามารถมีสิ่งนี้:

#include <stdio.h>
enum {a,b,c};
int main(){
  printf("%d\n",b);
  return 0;
}

1และออกจะนี้

สิ่งนี้จะถูกต้อง:

#include <stdio.h>
enum {a,b,c};
int bb=b;
int main(){
  printf("%d\n",bb);
  return 0;
}

และจะส่งออกเช่นเดียวกับก่อน

หากคุณทำสิ่งนี้:

enum {a,b,c};
enum {a,b,c};

คุณจะมีข้อผิดพลาด แต่ถ้าคุณทำสิ่งนี้:

enum alfa{a,b,c};
enum alfa;

คุณจะไม่มีข้อผิดพลาด

คุณสามารถทำสิ่งนี้:

enum {a,b,c};
int aa=a;

และจะเป็นตัวแปรจำนวนเต็มมีค่าaa 0แต่คุณสามารถทำสิ่งนี้:

enum {a,b,c} aa= a;

และจะมีผลเช่นเดียวกัน (นั่นคือaaการintมี0ค่า)

คุณยังสามารถทำสิ่งนี้:

enum {a,b,c} aa= a;
aa= 7;

และaaจะมีค่าint7

เนื่องจากคุณไม่สามารถทำซ้ำคำจำกัดความคงที่เชิงสัญลักษณ์ด้วยการใช้enumดังที่ฉันได้กล่าวไปแล้วก่อนหน้านี้คุณต้องใช้แท็กถ้าคุณต้องการประกาศintvars ด้วยการใช้enum:

enum tag1 {a,b,c};
enum tag1 var1= a;
enum tag1 var2= b;

การใช้typedefมันเพื่อความปลอดภัยของคุณจากการเขียนแต่ละครั้งenum tag1เพื่อกำหนดตัวแปร ด้วยtypedefคุณสามารถพิมพ์Tag1:

typedef enum {a,b,c} Tag1;
Tag1 var1= a;
Tag1 var2= b;

คุณยังสามารถ:

typedef enum tag1{a,b,c}Tag1;
Tag1 var1= a;
enum tag1 var2= b;

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

enum {A,B,C};

แทน

enum {a,b,c};

10

เป็นมูลค่าการกล่าวขวัญว่าใน C ++คุณสามารถใช้ "enum" เพื่อกำหนดประเภทใหม่โดยไม่ต้องใช้คำสั่ง typedef

enum Strategy {RANDOM, IMMEDIATE, SEARCH};
...
Strategy myStrategy = IMMEDIATE;

ฉันพบว่าวิธีนี้เป็นมิตรมากขึ้น

[แก้ไข - สถานะ C ++ ที่ชัดเจน - ฉันมีสิ่งนี้ในตอนแรกแล้วลบออก!]


ใช่คุณไม่ควรใช้ typedef กับ enums (หรือ structs, unions ฯลฯ ) ใน C ++

17
คำถามนี้มีไว้สำหรับ C ไม่ใช่สำหรับ C ++ ใน C โค้ดข้างต้นไม่ถูกต้องคุณต้องใช้typedefหรือระบุenumในการประกาศตัวแปรเช่น: enum Strategy {RANDOM, IMMEDIATE, SEARCH}; ... enum กลยุทธ์ myStrategy = ทันที;
Pavel Minaev

@pavel - ไม่ดี ฉันมี "ใน C ++" ในตอนแรกจากนั้นก็ทำการวิจัยบางอย่างที่ดูเหมือนจะขัดแย้งกัน
Roddy

ฉัน @Pavel enum Strategyคิดว่ามันควรจะเป็นคำตอบที่แยกต่างหากอธิบายประโยชน์ของการใช้ ฉันทำอย่างนั้นดูด้านล่าง
Johannes Schaub - litb

8

ดูเหมือนจะมีความสับสนเกี่ยวกับการประกาศ

เมื่อstrategyมาก่อน{RANDOM, IMMEDIATE, SEARCH}ดังต่อไปนี้

enum strategy {RANDOM, IMMEDIATE, SEARCH};

คุณกำลังสร้างชื่อenum strategyใหม่ อย่างไรก็ตามเมื่อประกาศตัวแปรคุณต้องใช้enum strategyตัวเอง strategyคุณไม่สามารถเพียงแค่ใช้ ดังนั้นต่อไปนี้ไม่ถูกต้อง

enum strategy {RANDOM, IMMEDIATE, SEARCH};
strategy a;

ในขณะที่ต่อไปนี้ถูกต้อง

enum strategy {RANDOM, IMMEDIATE, SEARCH};

enum strategy queen = RANDOM;
enum strategy king = SEARCH;
enum strategy pawn[100];

เมื่อstrategyมาถึง{RANDOM, IMMEDIATE, SEARCH}คุณกำลังสร้าง enum ที่ไม่ระบุชื่อและประกาศว่าstrategyเป็นตัวแปรประเภทนั้น

ดังนั้นตอนนี้คุณสามารถทำสิ่งที่ชอบ

enum {RANDOM, IMMEDIATE, SEARCH} strategy;
strategy = RANDOM;

อย่างไรก็ตามคุณไม่สามารถประกาศตัวแปรประเภทอื่นได้enum {RANDOM, IMMEDIATE, SEARCH}เนื่องจากคุณไม่เคยตั้งชื่อ ดังนั้นต่อไปนี้ไม่ถูกต้อง

enum {RANDOM, IMMEDIATE, SEARCH} strategy;
enum strategy a = RANDOM;

คุณสามารถรวมคำจำกัดความทั้งสองเข้าด้วยกัน

enum strategy {RANDOM, IMMEDIATE, SEARCH} a, b;

a = RANDOM;
b = SEARCH;
enum strategy c = IMMEDIATE;

Typedef ดังที่บันทึกไว้ก่อนหน้านี้ใช้สำหรับการสร้างการประกาศตัวแปรที่สั้นกว่า

typedef enum {RANDOM, IMMEDIATE, SEARCH} strategy;

ตอนนี้คุณได้บอกคอมไพเลอร์ที่enum {RANDOM, IMMEDIATE, SEARCH}เป็นอิสระไปstrategyแล้ว ดังนั้นตอนนี้คุณสามารถใช้strategyเป็นประเภทตัวแปรได้อย่างอิสระ คุณไม่จำเป็นต้องพิมพ์enum strategyอีกต่อไป ต่อไปนี้ถูกต้องในขณะนี้

strategy x = RANDOM;

คุณยังสามารถรวม Typedef พร้อมกับชื่อ enum เพื่อรับ

typedef enum strategyName {RANDOM, IMMEDIATE, SEARCH} strategy;

การใช้วิธีนี้มีประโยชน์ไม่มากนักนอกเหนือจากความจริงที่ว่าตอนนี้คุณสามารถใช้strategyและenum strategyNameเปลี่ยนได้

typedef enum strategyName {RANDOM, IMMEDIATE, SEARCH} strategy;

enum strategyName a = RANDOM;
strategy b = SEARCH;

1
คำตอบที่ดี ฉันยังเจอคำจำกัดความ enum เขียนเช่นนี้หรือtypedef enum strategy {RANDOM, IMMEDIATE, SEARCH} strategy typedef enum strategy {RANDOM, IMMEDIATE, SEARCH} strategy_typeมันมีข้อได้เปรียบมากกว่านี้typedef enum {RANDOM, IMMEDIATE, SEARCH} strategyไหม? คุณจะพิจารณาเพิ่มสิ่งเหล่านี้ในคำตอบเพื่อความสมบูรณ์หรือไม่
tjalling

ใช่. ฉันแก้ไขคำตอบของฉัน ตามความรู้ของฉันไม่มีประโยชน์ใด ๆ ที่สำคัญในกรณีทั่วไป
สับสน

2
เยี่ยมมากคำตอบของคุณครอบคลุมทุกอย่างแล้วขอบคุณ ความอัปยศมันเป็นรายการคำตอบที่ไม่ได้เกิดขึ้นน้อยมากเพราะมันตอบคำถามเดิมอย่างชัดเจนพร้อมคำอธิบายที่เหมาะสม
tjalling

2

หากคุณประกาศชื่อสำหรับการแจงนับจะไม่มีข้อผิดพลาดเกิดขึ้น

หากไม่ได้ประกาศคุณจะต้องใช้typedef:

enum enum_name {RANDOM, IMMEDIATE, SEARCH} strategy;
strategy = IMMEDIATE;

จะไม่แสดงข้อผิดพลาด ...


2

สิ่งที่ฉันชอบและใช้ในการก่อสร้างอยู่เสมอคือ:

typedef enum MyBestEnum
{
    /* good enough */
    GOOD = 0,
    /* even better */
    BETTER,
    /* divine */
    BEST
};

ฉันเชื่อว่านี่จะลบปัญหาที่คุณมี การใช้รูปแบบใหม่นั้นมาจากตัวเลือกในมุมมองของฉัน


1

คำตอบของ Tarc นั้นดีที่สุด

การถกเถียงเรื่อง Enum ส่วนใหญ่นั้นเป็นปลาเฮอริ่งแดง

เปรียบเทียบข้อมูลโค้ดนี้: -

int strategy;
strategy = 1;   
void some_function(void) 
{
}

ซึ่งจะช่วยให้

error C2501: 'strategy' : missing storage-class or type specifiers
error C2086: 'strategy' : redefinition

กับอันนี้ที่คอมไพล์โดยไม่มีปัญหา

int strategy;
void some_function(void) 
{
    strategy = 1;   
}

ตัวแปรstrategyต้องถูกตั้งค่าไว้ที่การประกาศหรือภายในฟังก์ชั่นอื่น ๆ คุณไม่สามารถเขียนซอฟต์แวร์ตามอำเภอใจ - โดยเฉพาะการมอบหมาย - ที่ขอบเขตทั่วโลก

ความจริงที่ว่าเขาใช้ enum {RANDOM, IMMEDIATE, SEARCH} แทนที่จะเป็น int นั้นมีความเกี่ยวข้องกับระดับความสับสนที่ผู้คนไม่สามารถมองเห็นได้ ข้อความแสดงข้อผิดพลาดการกำหนดนิยามใหม่ในคำถามแสดงว่านี่คือสิ่งที่ผู้เขียนทำผิด

ดังนั้นตอนนี้คุณน่าจะเห็นได้ว่าทำไมตัวอย่างแรกด้านล่างนี้จึงผิดและอีกสามตัวนั้นไม่เป็นไร

ตัวอย่างที่ 1 ผิด!

enum {RANDOM, IMMEDIATE, SEARCH} strategy;
strategy = IMMEDIATE;
void some_function(void) 
{
}

ตัวอย่างที่ 2

enum {RANDOM, IMMEDIATE, SEARCH} strategy = IMMEDIATE;
void some_function(void) 
{
}

ตัวอย่างที่ 3

enum {RANDOM, IMMEDIATE, SEARCH} strategy;
void some_function(void) 
{
    strategy = IMMEDIATE;
}

ตัวอย่างที่ 4

void some_function(void) 
{
    enum {RANDOM, IMMEDIATE, SEARCH} strategy;
    strategy = IMMEDIATE;
}

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


0

ฉันพยายามกับ gcc และเกิดขึ้นกับความต้องการของฉันฉันถูกบังคับให้ใช้ทางเลือกสุดท้ายเพื่อรวบรวมโดยไม่เกิดข้อผิดพลาด

typedef enum state {a = 0, b = 1, c = 2} สถานะ ;

typedef enum state {a = 0, b = 1, c = 2} state;

typedef enum state old; // New type, alias of the state type.
typedef enum state new; // New type, alias of the state type.

new now     = a;
old before  = b;

printf("State   now = %d \n", now);
printf("Sate before = %d \n\n", before);

newเป็นตัวเลือกที่ไม่ถูกต้องของตัวระบุในตระกูล C เนื่องจากตัวดำเนินการใน C ++
jww

0

enum stuff q;
enum stuff {a, b=-4, c, d=-2, e, f=-3, g} s;

การประกาศที่ทำหน้าที่เป็นคำนิยามที่แน่นอนของจำนวนเต็มที่ลงนามsด้วยประเภทที่สมบูรณ์และการประกาศซึ่งทำหน้าที่เป็นคำนิยามที่แน่นอนของจำนวนเต็มที่ลงนามqด้วยประเภทที่ไม่สมบูรณ์ในขอบเขต (ซึ่งจะแก้ไขให้เป็นประเภทที่สมบูรณ์ในขอบเขต ขอบเขต) (เช่นคำจำกัดความเบื้องต้นใด ๆ ตัวระบุqและsสามารถประกาศใหม่ด้วยรุ่นที่ไม่สมบูรณ์หรือสมบูรณ์ของประเภทเดียวกันintหรือenum stuffหลายครั้ง แต่กำหนดเพียงครั้งเดียวในขอบเขตเช่น int q = 3 และสามารถกำหนดใหม่ได้ในขอบเขตย่อยเท่านั้นและ ใช้งานได้หลังจากนิยาม) นอกจากนี้คุณยังสามารถใช้ประเภทที่สมบูรณ์enum stuffเพียงครั้งเดียวในขอบเขตเพราะมันทำหน้าที่เป็นคำนิยามประเภท

คอมไพเลอร์ชนิดคำจำกัดความการแจงนับสำหรับenum stuffทำยังมีอยู่ที่ขอบเขตไฟล์ (ใช้งานก่อนและด้านล่าง) เช่นเดียวกับการประกาศประเภทไปข้างหน้า (ประเภทenum stuffสามารถมีการประกาศหลาย ๆ แต่คำจำกัดความ / ความสมบูรณ์ในขอบเขตเดียวเท่านั้น . นอกจากนี้ยังทำหน้าที่เป็นคำสั่งคอมไพเลอร์เพื่อทดแทนaกับ rvalue 0, bกับ-4, cกับ5, dกับ-2, eกับ-3, fด้วย-1และgด้วย-2ในขอบเขตปัจจุบัน ค่าคงที่การแจงนับตอนนี้ใช้หลังจากการกำหนดจนกระทั่งนิยามใหม่ต่อไปใน enum อื่นซึ่งไม่สามารถอยู่ในระดับขอบเขตเดียวกัน

typedef enum bool {false, true} bool;

//this is the same as 
enum bool {false, true};
typedef enum bool bool;

//or
enum bool {false, true};
typedef unsigned int bool;

//remember though, bool is an alias for _Bool if you include stdbool.h. 
//and casting to a bool is the same as the !! operator 

แท็กเนมสเปซที่ใช้ร่วมกันโดย enum, struct และ union ถูกแยกออกและจะต้องนำหน้าด้วยคีย์เวิร์ด type (enum, struct หรือ union) ใน C คือหลังจากenum a {a} bนั้นenum a cต้องใช้และไม่a cใช้ เนื่องจากแท็กเนมสเปซแยกจากเนมสเปซของตัวระบุenum a {a} bจึงได้รับอนุญาต แต่enum a {a, b} bไม่ใช่เพราะค่าคงที่อยู่ในเนมสเปซเดียวกันกับตัวระบุตัวแปรนั่นคือเนมสเปซของตัวระบุ typedef enum a {a,b} bไม่อนุญาตด้วยเนื่องจาก typedef-names เป็นส่วนหนึ่งของ namespace ของตัวระบุ

ประเภทของenum boolและค่าคงที่เป็นไปตามรูปแบบต่อไปนี้ใน C:

+--------------+-----+-----+-----+
|   enum bool  | a=1 |b='a'| c=3 |  
+--------------+-----+-----+-----+
| unsigned int | int | int | int |  
+--------------+-----+-----+-----+

+--------------+-----+-----+-----+
|   enum bool  | a=1 | b=-2| c=3 |  
+--------------+-----+-----+-----+
|      int     | int | int | int |  
+--------------+-----+-----+-----+

+--------------+-----+---------------+-----+
|   enum bool  | a=1 |b=(-)0x80000000| c=2 |
+--------------+-----+---------------+-----+
| unsigned int | int |  unsigned int | int |
+--------------+-----+---------------+-----+

+--------------+-----+---------------+-----+
|   enum bool  | a=1 |b=(-)2147483648| c=2 |
+--------------+-----+---------------+-----+
| unsigned int | int |  unsigned int | int |
+--------------+-----+---------------+-----+

+-----------+-----+---------------+------+
| enum bool | a=1 |b=(-)0x80000000| c=-2 |
+-----------+-----+---------------+------+
|    long   | int |      long     |  int |
+-----------+-----+---------------+------+

+-----------+-----+---------------+------+
| enum bool | a=1 | b=2147483648  | c=-2 |
+-----------+-----+---------------+------+
|    long   | int |      long     |  int |
+-----------+-----+---------------+------+

+-----------+-----+---------------+------+
| enum bool | a=1 | b=-2147483648 | c=-2 |
+-----------+-----+---------------+------+
|    int    | int |      int      |  int |
+-----------+-----+---------------+------+

+---------------+-----+---------------+-----+
|   enum bool   | a=1 | b=99999999999 | c=1 |
+---------------+-----+---------------+-----+
| unsigned long | int | unsigned long | int |
+---------------+-----+---------------+-----+

+-----------+-----+---------------+------+
| enum bool | a=1 | b=99999999999 | c=-1 |
+-----------+-----+---------------+------+
|    long   | int |      long     |  int |
+-----------+-----+---------------+------+

รวบรวมสิ่งนี้ได้ดีใน C:

#include <stdio.h>
enum c j;
enum c{f, m} p;
typedef int d;
typedef int c;
enum c j;
enum m {n} ;
int main() {
  enum c j;
  enum d{l};
  enum d q; 
  enum m y; 
  printf("%llu", j);
}

C ++

ใน C ++, enums สามารถมีประเภทได้

enum Bool: bool {True, False} Bool;
enum Bool: bool {True, False, maybe} Bool; //error

ในสถานการณ์นี้ค่าคงที่และตัวระบุทั้งหมดมีชนิดเดียวกันบูลและข้อผิดพลาดจะเกิดขึ้นหากไม่สามารถแสดงตัวเลขด้วยชนิดนั้น อาจ = 2 ซึ่งไม่ใช่บูล นอกจากนี้จริงเท็จและ Bool ไม่สามารถเป็นตัวพิมพ์เล็กมิฉะนั้นพวกเขาจะปะทะกับคำหลักภาษา enum ยังไม่สามารถมีชนิดพอยน์เตอร์ได้

กฎสำหรับ enums แตกต่างกันใน C ++

#include <iostream>
c j; //not allowed, unknown type name c before enum c{f} p; line
enum c j; //not allowed, forward declaration of enum type not allowed and variable can have an incomplete type but not when it's still a forward declaration in C++ unlike C
enum c{f, m} p;
typedef int d;
typedef int c; // not allowed in C++ as it clashes with enum c, but if just int c were used then the below usages of c j; would have to be enum c j;
[enum] c j;
enum m {n} ;
int main() {
  [enum] c j;
  enum d{l}; //not allowed in same scope as typedef but allowed here 
  d q;
  m y; //simple type specifier not allowed, need elaborated type specifier enum m to refer to enum m here
  p v; // not allowed, need enum p to refer to enum p
  std::cout << j;
}

ตัวแปร Enums ใน C ++ ไม่ได้เป็นเพียงจำนวนเต็มที่ไม่ได้ลงชื่ออีกต่อไป แต่ยังเป็น enum type และสามารถกำหนดค่าคงที่ใน enum ได้อีกด้วย อย่างไรก็ตามเรื่องนี้สามารถถูกโยนทิ้งไป

#include <stdio.h>
enum a {l} c;
enum d {f} ;
int main() {
  c=0; // not allowed;
  c=l;
  c=(a)1;
  c=(enum a)4;
  printf("%llu", c); //4
}

คลาส Enum

enum struct เหมือนกันกับ enum class

#include <stdio.h>
enum class a {b} c;
int main() {
  printf("%llu", a::b<1) ; //not allowed
  printf("%llu", (int)a::b<1) ;
  printf("%llu", a::b<(a)1) ;
  printf("%llu", a::b<(enum a)1);
  printf("%llu", a::b<(enum class a)1) ; //not allowed 
  printf("%llu", b<(enum a)1); //not allowed
}

ตัวดำเนินการแก้ไขปัญหาขอบเขตยังคงสามารถใช้สำหรับ enums ที่ไม่มีขอบเขต

#include <stdio.h>
enum a: bool {l, w} ;
int main() {
  enum a: bool {w, l} f;
  printf("%llu", ::a::w);
}

แต่เนื่องจาก w ไม่สามารถนิยามเป็นอย่างอื่นในขอบเขตจึงไม่มีความแตกต่างระหว่าง::wและ::a::w

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.