Enum вызывает многократно определенную ошибку, в то время как typedef enum doesnt

Я выполняю код C.

Скажем, у меня есть файл заголовка, который содержит перечисление. Я включаю этот файл в 2 файла c - Bc и Cc

До нашей эры:

#include A.h
//....other code...

Cc

#include A.h
//....other code...

Когда Ah содержит перечисление:

ах

#ifndef A_H
#define A_H

enum my_enum {

 //...enum content...

} my_enum;

//...other code...

#endif

когда определено так, я получаю "символ" my_enum "многократно определенную" ошибку от компилятора, который является understandable-, поскольку я определил перечисление в файле заголовка.

Однако этого не происходит, когда я набираю enum-

ах

#ifndef A_H
#define A_H

typedef enum my_enum {

 //...enum content...

} my_enum;

//...other code...

#endif

Это, конечно, происходит независимо от того, какой код находится в файлах.c (кроме включения Ah)

Каковы причины этого? Почему это не множественное определение, когда я печатал перечисление?

3 ответа

enum my_enum {

 //...enum content...

} my_enum;

my_enum здесь не тип, а переменная типа enum my_enum. Включение этого в заголовок приводит к множественному определению переменной my_enum.

typedef enum my_enum {

 //...enum content...

} my_enum;

my_enum здесь тип, а не переменная. Это тип такой же, как enum my_enum. Это функция typedef.


В C существуют разные пространства имен. У нас есть такие правила "помех" (или нет) идентификаторов:

  • Идентификаторы в разных областях не находятся в conflct.
  • Идентификаторы в том же объеме, но принадлежащие к разным пространствам имен, не конфликтуют.

Эти пространства имен:

  1. Обычные идентификаторы (обозначающие объекты, функции, имена typedef и константы перечисления).
  2. enum, struct, union tags.
  3. struct/union.
  4. Ярлыки (используются с goto).

Таким образом, например, поскольку имена typedef, теги enum, члены struct и метки находятся в разных пространствах имен, следующий код не имеет конфликтов:

int main(void) // "x" is always in diffrent name spaces and/or scopes
 {
 typedef struct { struct { float x; } x; } x;
 enum x { zero = 0 } value = zero;

 x: // Label

 if (value != 0)
 goto x;

 { // This block is another scope

 typedef enum x { one = 1 } x;
 x w = one;
 }
 }

Для справки см. Раздел 6.2.3 стандартного документа C: Стандарт C99, TC3


Когда вы используете typedef, он будет обрабатывать my_enum как просто псевдоним enum.

т.е. в этом случае my_enum ведет себя как тип, а не переменная.

Если вы не используете typedef, это будет несколько объявлений.

licensed under cc by-sa 3.0 with attribution.