Làm thế nào để xác định một kiểu liệt kê (enum) trong C?


272

Tôi không chắc cú pháp thích hợp để sử dụng C enums là gì. Tôi có đoạn mã sau:

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

Nhưng điều này không biên dịch, với lỗi sau:

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

Tôi đang làm gì sai?


7
Câu hỏi lâu năm, có lẽ không ai sẽ thấy điều này; nhưng tại sao điều này lại gây ra lỗi? Nó sẽ hoạt động hoàn toàn tốt như trong câu hỏi theo như kiến ​​thức của tôi.
Utkan Gezer

2
@Solver tại sao cú pháp này sai?
MCG

6
@MCQ, hoại tử necro'd necro: Cú pháp được trình bày trong câu hỏi không sai trong C. Nó tuyên bố strategylà có một kiểu liệt kê ẩn danh và gán một trong các giá trị khai báo của loại đó cho nó. Hơn nữa, nếu tôi bọc mã được trình bày trong một main()hàm tầm thường khác thì nó sẽ biên dịch tốt cho tôi, thậm chí không có cảnh báo, với gcc 4.4.7. Một số câu trả lời ngụ ý giống nhau, mặc dù không có nhiều từ.
John Bollinger

5
Hầu hết các câu trả lời đều thiếu thực tế là hai dòng mã trong câu hỏi không chỉ là một đoạn trích. Chúng là toàn bộ tệp nguồn. Nếu hai dòng đó được bao gồm trong phần thân của hàm, không có lỗi. Nếu chúng xuất hiện ở phạm vi tệp, bên ngoài bất kỳ khai báo chức năng nào, bạn sẽ nhận được các lỗi mà OP đã hỏi về (cộng với một số lỗi khác khi tôi thử). Vấn đề cơ bản là trình biên dịch đang cố xử lý strategy = IMMEDIATE;như một khai báo. Nó có một hình thức có thể là hợp pháp trong tiền ANSI C, nhưng trong C hiện đại thì nó là bất hợp pháp. Bài tập không được phép ở phạm vi tập tin.
Keith Thompson

3
@Solver: enum strategy { ... };định nghĩa một kiểu liệt kê có tên enum strategy, đó strategylà thẻ. enum { ... } strategy;định nghĩa một kiểu liệt kê ẩn danh (không có thẻ) một đối tượng của loại đó được đặt tên strategy. Cả hai đều hoàn toàn hợp pháp; chúng chỉ có nghĩa là những thứ khác nhau.
Keith Thompson

Câu trả lời:


377

Khai báo một biến enum được thực hiện như thế này:

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

Tuy nhiên, bạn có thể sử dụng a typedefđể rút ngắn các khai báo biến, như vậy:

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

Có một quy ước đặt tên để phân biệt giữa các loại và các biến là một ý tưởng tốt:

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

1
Nhưng OP muốn có một loại enum ẩn danh
osvein

Tôi không thể chỉ gõ enum MyEnum {} myVar;và sau đó sử dụng biến myVarnhư sau:myVar = SOMEENUMCONSTANT;
Mushy

451

Thật đáng để chỉ ra rằng bạn không cần a typedef. Bạn chỉ có thể làm như sau

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

Đó là một câu hỏi phong cách cho dù bạn thích typedef. Nếu không có nó, nếu bạn muốn tham khảo loại liệt kê, bạn cần sử dụng enum strategy. Với nó, bạn chỉ có thể nóistrategy .

Cả hai cách đều có pro và nhược điểm của họ. Cái này dài dòng hơn, nhưng giữ các định danh loại vào không gian tên thẻ nơi chúng sẽ không xung đột với các định danh thông thường (nghĩ về struct statstatchức năng: chúng không xung đột) và ngay lập tức bạn thấy đó là một loại. Cái kia ngắn hơn, nhưng đưa định danh kiểu vào không gian tên thông thường.


6
Nó không phải là câu trả lời được chấp nhận vì nó sai. Bạn không thể sử dụng chiến lược enum {...}; trong C - bạn có thể và nên làm điều đó trong C ++.
Rõ ràng hơn

19
@Clearer: Mã này hoạt động hoàn hảo. Đây là một ví dụ hoạt động: ideone.com/T0YV17 Lưu ý rằng nó sử dụng enumtừ khóa trên cả hai dòng.
RichieHulum

Hoặc "chiến lược typedef enum {RANDOM, IMMEDIATE, SEARCH} Strateg_t;" và nhà phát triển sử dụng enum có thể sử dụng bất kỳ quy ước nào họ muốn.
Andy Nugent

điều này hoạt động rất tốt: enum strategy { RANDOM, IMMEDIATE, SEARCH }; sau đó khi bạn muốn có một thể hiện của enum đó: `enum Strateg myEnum;
dùng3629249

2
@AndyNugent đừng làm vậy! * _t loại được bảo lưu bởi POSIX
osvein

58

Bạn đang cố gắng khai báo strategyhai lần và đó là lý do tại sao bạn gặp phải lỗi trên. Các công việc sau đây mà không có bất kỳ khiếu nại (biên dịch với 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;
}

Nếu thay vì ở trên, dòng thứ hai đã được thay đổi thành:

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

Từ các cảnh báo, bạn có thể dễ dàng thấy lỗi của mình:

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

Vì vậy, trình biên dịch đã strategy = IMMEDIATEkhai báo một biến được gọi strategyvới kiểu mặc địnhint , nhưng đã có một khai báo trước đó của một biến có tên này.

Tuy nhiên, nếu bạn đặt phép gán trong main()hàm, nó sẽ là một mã hợp lệ:

#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

Khi bạn nói

enum {RANDOM, IMMEDIATE, SEARCH} strategy;

bạn tạo một biến đối tượng duy nhất, được gọi là 'chiến lược' của một enum không tên. Đây không phải là một điều rất hữu ích để làm - bạn cần một typedef:

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

9
Tại sao điều này không hữu ích? Nếu tôi không quan tâm đến tên của loại, tại sao tôi nên đặt tên? Điều duy nhất dự định ở đây là đặt tên cho biến, vì vậy có thể gán giá trị mới cho biến đó.
MSalters

3
Tôi nói nó không RẤT hữu ích, và tôi không tin là có. Chắc chắn, tôi không sử dụng mẫu này trong mã của riêng tôi. YMMV.

3
@HorseSMith Một enum không tên không hữu ích lắm vì bạn không thể có bất kỳ biến nào khác của loại đó, hoặc tham số hàm hoặc giá trị trả về. Nếu một biến là tất cả những gì bạn cần, thì nó vẫn ổn.
Bob Stein

3
Ai đó không sử dụng enums nặc danh không chứng minh rằng họ không có sử dụng. Bạn không cần typedef. Một số nguyên tắc mã (kernel.org/doc/Documentation/CodingStyle) thậm chí không khuyến khích nó.
martinkunev

2
Câu trả lời này C ALNG gây hiểu lầm. Câu trả lời của Tarc là duy nhất đúng ở đây.
nightpool

13

Như đã viết, không có gì sai với mã của bạn. Bạn có chắc là bạn chưa làm gì đó như

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

Những dòng nào thông báo lỗi chỉ đến? Khi nó nói "tuyên bố trước đây về" chiến lược "đã ở đây", "ở đây" là gì và nó thể hiện điều gì?


6
Anh ta có lẽ đã làm strategy = IMMEDIATE;ở phạm vi tập tin. Một nhiệm vụ không thể xảy ra ở phạm vi tệp bên ngoài tất cả các chức năng. Vì vậy, trình biên dịch đã cố gắng khắc phục lỗi tốt nhất và cho rằng ý của anh ta là int strategy = IMMEDIATE;tại thời điểm đó đã xảy ra xung đột.
Julian Schaub - litb

2
Đây là câu trả lời tốt nhất, có sự nhầm lẫn nhầy nhụa trong các câu trả lời khác thật đau đớn.
thư giãn

12

@ThoAppelsin trong bình luận của mình cho câu hỏi được đăng là đúng. Đoạn mã được đăng trong câu hỏi nó hợp lệ và không có lỗi. Lỗi bạn phải có do cú pháp xấu khác ở bất kỳ vị trí nào khác của tệp nguồn c của bạn. enum{a,b,c};định nghĩa ba hằng số tượng trưng ( a, bc) mà là các số nguyên có giá trị 0, 12tương ứng, nhưng khi chúng tôi sử dụng enumđó là vì chúng ta thường không quan tâm đến giá trị số nguyên cụ thể, chúng tôi quan tâm nhiều hơn về ý nghĩa của tên hằng số tượng trưng. Điều này có nghĩa là bạn có thể có điều này:

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

và điều này sẽ xuất ra 1 .

Điều này cũng sẽ hợp lệ:

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

và sẽ xuất ra như trước.

Nếu bạn làm điều này:

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

bạn sẽ gặp lỗi, nhưng nếu bạn làm điều này:

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

bạn sẽ không có bất kỳ lỗi nào

bạn có thể làm được việc này:

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

aasẽ là một biến số nguyên có giá trị 0. nhưng bạn cũng có thể làm điều này:

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

và sẽ có tác dụng tương tự (có nghĩa là, aatrở thành một intvới 0giá trị).

bạn cũng có thể làm điều này:

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

aasẽ intcó giá trị 7.

bởi vì bạn không thể lặp lại định nghĩa hằng số tượng trưng với việc sử dụng enum, như tôi đã nói trước đây, bạn phải sử dụng các thẻ nếu bạn muốn khai báo các intvars với việc sử dụng enum:

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

việc sử dụng typedefnó là để bảo vệ bạn khỏi việc viết mỗi lần enum tag1để xác định biến. Với typedefbạn chỉ có thể gõ Tag1:

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

Bạn cũng có thể có:

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

Điều cuối cùng để nói là vì chúng ta đang nói về các hằng số tượng trưng được xác định, tốt hơn là sử dụng các chữ cái viết hoa khi sử dụng enum, đó là ví dụ:

enum {A,B,C};

thay vì

enum {a,b,c};

10

Điều đáng nói là trong C ++, bạn có thể sử dụng "enum" để xác định loại mới mà không cần câu lệnh typedef.

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

Tôi thấy cách tiếp cận này thân thiện hơn rất nhiều.

[chỉnh sửa - làm rõ trạng thái C ++ - Ban đầu tôi đã có nó, sau đó xóa nó!]


Có, bạn không bao giờ nên sử dụng typedef với enums (hoặc structs, unions, v.v.) trong C ++.

17
Câu hỏi này dành cho C, không phải cho C ++. Trong C, mã trên không hợp lệ - bạn cũng phải sử dụng typedefhoặc chỉ định enumtrong khai báo biến: enum Strateg {RANDOM, IMMEDIATE, SEARCH}; ... enum Chiến lược myStrargety = NGAY LẬP TỨC;
Pavel Minaev

@pavel - xấu của tôi. Tôi đã có "trong C ++" ban đầu, sau đó thực hiện một số nghiên cứu dường như mâu thuẫn với điều đó.
Roddy

@Pavel Tôi nghĩ rằng nó nên là một câu trả lời riêng biệt mô tả lợi ích của việc sử dụng enum Strategy. Tôi đã làm điều đó, xem dưới đây.
Johannes Schaub - litb

8

Dường như có một sự nhầm lẫn về tuyên bố.

Khi strategyđến trước {RANDOM, IMMEDIATE, SEARCH}như sau,

enum strategy {RANDOM, IMMEDIATE, SEARCH};

bạn đang tạo một loại mới có tên enum strategy. Tuy nhiên, khi khai báo biến, bạn cần sử dụng enum strategychính nó. Bạn không thể chỉ sử dụng strategy. Vì vậy, sau đây là không hợp lệ.

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

Trong khi, những điều sau đây là hợp lệ

enum strategy {RANDOM, IMMEDIATE, SEARCH};

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

Khi strategyđến sau {RANDOM, IMMEDIATE, SEARCH}, bạn đang tạo một enum ẩn danh và sau đó khai strategybáo là một biến của loại đó.

Vì vậy, bây giờ, bạn có thể làm một cái gì đó như

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

Tuy nhiên, bạn không thể khai báo bất kỳ biến loại nào khác enum {RANDOM, IMMEDIATE, SEARCH}vì bạn chưa bao giờ đặt tên cho nó. Vì vậy, sau đây là không hợp lệ

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

Bạn cũng có thể kết hợp cả hai định nghĩa

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

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

Typedef như đã lưu ý trước đây được sử dụng để tạo một khai báo biến ngắn hơn.

typedef enum {RANDOM, IMMEDIATE, SEARCH} strategy;

Bây giờ bạn đã nói với trình biên dịch đó enum {RANDOM, IMMEDIATE, SEARCH}là đồng bộ với strategy. Vì vậy, bây giờ bạn có thể tự do sử dụng strategynhư loại biến. Bạn không cần phải gõ enum strategynữa. Sau đây là hợp lệ

strategy x = RANDOM;

Bạn cũng có thể kết hợp Typedef cùng với tên enum để có được

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

Không có nhiều lợi thế của việc sử dụng phương pháp này ngoài thực tế là bây giờ bạn có thể sử dụng strategyenum strategyNamethay thế cho nhau.

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

enum strategyName a = RANDOM;
strategy b = SEARCH;

1
Câu trả lời chính xác. Tôi cũng đã bắt gặp các định nghĩa enum được viết như thế này: typedef enum strategy {RANDOM, IMMEDIATE, SEARCH} strategyhoặc typedef enum strategy {RANDOM, IMMEDIATE, SEARCH} strategy_type. Điều đó có bất kỳ lợi thế hơn typedef enum {RANDOM, IMMEDIATE, SEARCH} strategy? Bạn có muốn xem xét thêm những câu này vào câu trả lời của bạn không?
bắt đầu từ

Đúng. Tôi đã sửa đổi câu trả lời của tôi. Theo hiểu biết của tôi, không có bất kỳ lợi thế lớn nào trong trường hợp chung.
Nhầm lẫn

2
Tuyệt vời, câu trả lời của bạn bao gồm tất cả bây giờ, cảm ơn. Một sự xấu hổ cho đến nay là danh sách các câu trả lời, không phải vì nó giải quyết rõ ràng câu hỏi ban đầu, với lời giải thích phù hợp.
bắt đầu

2

Nếu bạn khai báo tên để liệt kê thì sẽ không có lỗi xảy ra.

Nếu không được khai báo, bạn phải sử dụng typedef:

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

Nó sẽ không hiển thị lỗi ...


2

Xây dựng yêu thích và duy nhất của tôi luôn luôn là:

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

Tôi tin rằng điều này sẽ loại bỏ vấn đề của bạn. Sử dụng loại mới là từ quan điểm của tôi tùy chọn bên phải.


1

Câu trả lời của Tarc là tốt nhất.

Phần lớn các cuộc thảo luận enum là một cá trích đỏ.

So sánh đoạn mã này: -

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

cái nào cho

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

với cái này mà biên dịch không có vấn đề.

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

Biến strategy cần được đặt khi khai báo hoặc bên trong hàm, v.v. Bạn không thể viết phần mềm tùy ý - đặc biệt là các bài tập - ở phạm vi toàn cầu.

Việc anh ấy sử dụng enum {RANDOM, NGAY LẬP TỨC, TÌM KIẾM} thay vì int chỉ liên quan đến mức độ khiến mọi người bối rối không thể nhìn ra ngoài nó. Các thông báo lỗi xác định lại trong câu hỏi cho thấy đây là những gì tác giả đã làm sai.

Vì vậy, bây giờ bạn sẽ có thể thấy tại sao ví dụ đầu tiên dưới đây là sai và ba cái còn lại là ổn.

Ví dụ 1. SAU!

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

Ví dụ 2. QUYỀN.

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

Ví dụ 3. QUYỀN.

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

Ví dụ 4. QUYỀN.

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

Nếu bạn có một chương trình làm việc, bạn sẽ chỉ có thể dán các đoạn mã này vào chương trình của bạn và thấy rằng một số biên dịch và một số thì không.


0

Tôi đã thử với gcc và đưa ra nhu cầu của mình, tôi buộc phải sử dụng phương án cuối cùng, để biên dịch với lỗi.

trạng thái typedef enum {a = 0, b = 1, c = 2} trạng thái ;

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);

newlà một lựa chọn không tốt về định danh trong họ C vì nó là toán tử trong C ++.
jww

0

C

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

sKhai báo hoạt động như một định nghĩa dự kiến ​​của một số nguyên đã ký với kiểu hoàn chỉnh và khai báo hoạt động như một định nghĩa dự kiến ​​của số nguyên đã ký qvới loại không đầy đủ trong phạm vi (phân giải thành loại hoàn chỉnh trong phạm vi vì định nghĩa loại có ở bất kỳ đâu trong phạm vi) (giống như bất kỳ định nghĩa dự kiến ​​nào, các định danh qscó thể được phân phối lại với phiên bản chưa hoàn chỉnh hoặc đầy đủ cùng loại inthoặc enum stuffnhiều lần nhưng chỉ được xác định một lần trong phạm vi tức là int q = 3; và chỉ có thể được xác định lại trong một phạm vi con và chỉ có thể sử dụng sau khi định nghĩa). Ngoài ra, bạn chỉ có thể sử dụng loại hoàn chỉnh enum stuffmột lần trong phạm vi vì nó hoạt động như một định nghĩa loại.

Một định nghĩa kiểu liệt kê trình biên dịch cho enum stuffcũng được trình bày ở phạm vi tệp (có thể sử dụng trước và bên dưới) cũng như khai báo kiểu chuyển tiếp (loại enum stuffcó thể có nhiều khai báo nhưng chỉ có một định nghĩa / hoàn thành trong phạm vi và có thể được định nghĩa lại trong một phạm vi con) . Nó cũng hoạt động như một chỉ thị của trình biên dịch để thay thế abằng rvalue 0, bvới -4, cvới 5, dvới -2, evới -3, fvới -1gvới -2trong phạm vi hiện tại. Các hằng số liệt kê hiện được áp dụng sau định nghĩa cho đến khi xác định lại tiếp theo trong một enum khác không thể ở cùng một phạm vi.

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 

Không gian tên thẻ được chia sẻ bởi enum, struct và union là riêng biệt và phải được thêm tiền tố bởi từ khóa loại (enum, struct hoặc union) trong C tức là sau enum a {a} b, enum a cphải được sử dụng và không a c. Bởi vì không gian tên thẻ tách biệt với không gian tên định danh, enum a {a} bđược phép nhưng enum a {a, b} bkhông phải vì các hằng số nằm trong cùng một không gian tên với các định danh biến, không gian tên định danh. typedef enum a {a,b} bcũng không được phép vì tên typedef là một phần của không gian tên định danh.

Loại enum boolvà hằng số theo mẫu sau trong 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 |
+-----------+-----+---------------+------+

Điều này biên dịch tốt trong 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 ++

Trong C ++, enums có thể có một loại

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

Trong tình huống này, các hằng số và mã định danh đều có cùng loại, bool và sẽ xảy ra lỗi nếu một số không thể được đại diện bởi loại đó. Có lẽ = 2, đó không phải là một bool. Ngoài ra, True, false và Bool không thể viết thường nếu không chúng sẽ xung đột với các từ khóa ngôn ngữ. Một enum cũng không thể có một loại con trỏ.

Các quy tắc cho enums là khác nhau trong 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;
}

Các biến Enums trong C ++ không còn là các số nguyên không dấu, v.v., chúng cũng thuộc loại enum và chỉ có thể được gán các hằng số trong enum. Điều này tuy nhiên có thể được bỏ đi.

#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
}

Lớp học Enum

enum struct giống hệt với 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
}

Toán tử phân giải phạm vi vẫn có thể được sử dụng cho các enum không có phạm vi.

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

Nhưng vì w không thể được định nghĩa là một cái gì đó khác trong phạm vi, nên không có sự khác biệt giữa ::w::a::w

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.