Перечисляемый тип

Теги: Си перечисление, enum.



Перечисляемый тип

В си выделен отдельный тип перечисление (enum), задающий набор всех возможных целочисленных значений переменной этого типа. Синтаксис перечисления

enum <имя> {
        <имя поля 1>,
        <имя поля 2>,
        ...
        <имя поля N>
};      //здесь стоит ;!

Например

#include <conio.h>
#include <stdio.h>

enum Gender {
        MALE,
        FEMALE
};

void main() {
        enum Gender a, b;
        a = MALE;
        b = FEMALE;
        printf("a = %d\n", a);
        printf("b = %d\n", b);
        getch();
}

В этой программе объявлено перечисление с именем Gender. Переменная типа enum Gender может принимать теперь только два значения – это MALE И FEMALE.

По умолчанию, первое поле структуры принимает численное значение 0, следующее 1, следующее 2 и т.д. Можно задать нулевое значение явно:

#include <conio.h>
#include <stdio.h>

enum Token {
        SYMBOL,                 //0
        NUMBER,                 //1
        EXPRESSION = 0, //0
        OPERATOR,               //1
        UNDEFINED               //2
};

void main() {
        enum Token a, b, c, d, e;
        a = SYMBOL;
        b = NUMBER;
        c = EXPRESSION;
        d = OPERATOR;
        e = UNDEFINED;
        printf("a = %d\n", a);
        printf("b = %d\n", b);
        printf("c = %d\n", c);
        printf("d = %d\n", d);
        printf("e = %d\n", e);
        getch();
}

Будут выведены значения 0 1 0 1 2. То есть, значение SYMBOL равно значению EXPRESSION, а NUMBER равно OPERATOR. Если мы изменим программу и напишем

enum Token {
        SYMBOL,                         //0
        NUMBER,                         //1
        EXPRESSION = 10,        //10
        OPERATOR,                       //11
        UNDEFINED                       //12
};

То SYMBOL будет равно значению 0, NUMBER равно 1, EXPRESSION равно 10, OPERATOR равно 11, UNDEFINED равно 12.

Принято писать имена полей перечисления, как и константы, заглавными буквами. Так как поля перечисления целого типа, то они могут быть использованы в операторе switch.

Заметьте, что мы не можем присвоить переменной типа Token просто численное значение. Переменная является сущностью типа Token и принимает только значения полей перечисления. Тем не менее, переменной числу можно присвоить значение поля перечисления.

Обычно перечисления используются в качестве набора именованных констант. Часто поступают следующим образом - создают массив строк, ассоциированных с полями перечисления. Например

#include <conio.h>
#include <stdio.h>
#include <stdlib.h>

static char *ErrorNames[] = {
        "Index Out Of Bounds",
        "Stack Overflow",
        "Stack Underflow",
        "Out of Memory"
};

enum Errors {
        INDEX_OUT_OF_BOUNDS = 1,
        STACK_OVERFLOW,
        STACK_UNDERFLOW,
        OUT_OF_MEMORY
};

void main() {
        //ошибка случилась
        printf(ErrorNames[INDEX_OUT_OF_BOUNDS-1]);
        exit(INDEX_OUT_OF_BOUNDS);
}

Так как поля принимают численные значения, то они могут использоваться в качестве индекса массива строк. Команда exit(N) должна получать код ошибки, отличный от нуля, потому что 0 - это плановое завершение без ошибки. Именно поэтому первое поле перечисления равно единице.

Перечисления используются для большей типобезопасности и ограничения возможных значений переменной. Для того, чтобы не писать enum каждый раз, можно объявить новый тип. Делается это также, как и в случае структур.

typedef enum enumName {
        FIELD1,
        FIELD2
} Name;

Например

typedef enum Bool {
        FALSE,
        TRUE
} Bool;
Q&A

Всё ещё не понятно? – пиши вопросы на ящик email
Структуры