С
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
в текущей области видимости. Константы перечисления теперь применяются после определения до следующего переопределения в другом перечислении, которое не может быть на том же уровне области действия.
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 являются частью пространства имен идентификатора.
Тип 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 ++ перечисления могут иметь тип
enum Bool: bool {True, False} Bool;
enum Bool: bool {True, False, maybe} Bool; //error
В этой ситуации все константы и идентификатор имеют одинаковый тип, bool, и произойдет ошибка, если число не может быть представлено этим типом. Возможно = 2, что не является булом. Кроме того, True, False и Bool не могут быть строчными, иначе они будут конфликтовать с ключевыми словами языка. Перечисление также не может иметь тип указателя.
Правила для перечислений различны в 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 ++ больше не являются целыми числами без знака и т. Д., Они также имеют тип 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
}
Оператор разрешения контекста все еще может использоваться для неперечисленных перечислений.
#include <stdio.h>
enum a: bool {l, w} ;
int main() {
enum a: bool {w, l} f;
printf("%llu", ::a::w);
}
Но поскольку вес не может быть определена как - то еще в объеме, нет никакой разницы между ::w
и::a::w