2013-07-29 27 views
5

Nella biblioteca FreeImagePlus, in FreeImage.h, c'è un divertente #define che sembra creare una typedef e un enum con lo stesso nome:Typedef e enum con lo stesso nome?

#define FI_ENUM(x)  typedef int x; enum x 

Questo si espande dal preprocessore di codice come:

typedef int FREE_IMAGE_FILTER; 
enum FREE_IMAGE_FILTER { 
FILTER_BOX = 0, 
FILTER_BICUBIC = 1, 
[...] 

Cosa fa? È legale avere uno typedef e uno enum con lo stesso nome? E non è un enum compatibile allo int? Perché FreeImage fa questo?

risposta

6

Nomi di strutture, unioni e elenchi di vite vivono nel proprio spazio dei nomi. Ecco perché è possibile dichiarare una variabile struct/union/enum con lo stesso nome del numero effettivo struct/union/enum.

e non è il nome del completo enum (ad esempio per enum X intendo la X) che deve essere compatibile con un numero intero, è il nome all'interno l'enumerazione.

+0

Grazie, non conoscevo i namespace. Ancora, dove aiuta il "typedef int"? C'è qualche codice che si rompe senza di esso? – sleske

+0

@sleske In generale non è necessario, si potrebbe anche fare 'typedef enum X {...} X;' A meno che non ci siano operazioni su variabili di tipo 'X' che non possono essere eseguite sui tipi di enumerazione. –

0

Citando C99 N1256 draft 6.2.1 "Scopes di identificatori":

Un identificatore può denotare un oggetto; una funzione; un tag o un membro di una struttura, unione o enumerazione; un nome typedef; un nome di etichetta; un nome macro; o un parametro macro.

il che significa che in:

typedef int id; 

id è un identificatore.

E da 6.2.3 "spazi Nome di identificatori":

BEGIN PREVENTIVO

Se più di una dichiarazione di un particolare identificativo è visibile in qualsiasi punto di un'unità di traduzione, il contesto sintattico disambigua usi che si riferiscono a diverse entità. Pertanto, vi sono spazi dei nomi separati per varie categorie di identificatori, come segue:

  • nomi di etichette (non chiariti dalla sintassi della dichiarazione dell'etichetta e uso);
  • tag delle strutture, dei sindacati e delle enumerazioni (disambiguato seguendo una delle parole chiave struct, union o enum);
  • i membri di strutture o sindacati; ogni struttura o unione ha uno spazio dei nomi separato per i suoi membri (disambiguato dal tipo di espressione utilizzato per accedere al membro tramite l'operatore. o ->);
  • tutti gli altri identificatori, denominati identificatori ordinari (dichiarati in dichiaratori ordinari o come costanti di enumerazione).

Termina citazione

Così in:

typedef int id; 
enum id {ID0}; 
  • il primo id è un identificatore normale
  • il secondo è un identificatore tag

un entrambi possono coesistere pacificamente.

D'altra parte, non abbiamo potuto fare qualcosa di simile:

typedef int id; 
int id; 

perché entrambi sarebbe identificatori ordinari.