2011-12-21 4 views
36

ho trovato questo codice nella intestazioni di Linux, /usr/include/dirent.h:Qual è lo scopo di questi #define all'interno di una enumerazione?

enum 
    {  
    DT_UNKNOWN = 0, 
# define DT_UNKNOWN DT_UNKNOWN 
    DT_FIFO = 1, 
# define DT_FIFO DT_FIFO 
    DT_CHR = 2, 
# define DT_CHR  DT_CHR 
    DT_DIR = 4, 
# define DT_DIR  DT_DIR 
    DT_BLK = 6, 
# define DT_BLK  DT_BLK 
    DT_REG = 8, 
# define DT_REG  DT_REG 
    DT_LNK = 10, 
# define DT_LNK  DT_LNK 
    DT_SOCK = 12, 
# define DT_SOCK DT_SOCK 
    DT_WHT = 14 
# define DT_WHT  DT_WHT 
    }; 

cosa è questo costrutto per? - perché definire qualcosa con una stringa identica, che verrà poi compilata al valore int?

+0

Forse c'erano solo definizioni, e qualcuno ha aggiunto l'enum in seguito. – Chris

risposta

21

La mia ipotesi è che qualche altro codice possa quindi verificare se uno (o più di) di questi valori enum è stato definito usando #ifdef.

+3

Il meglio dei due mondi: controlla la definizione con '# ifdef', ma viene comunque visualizzato come nome simbolico nel debug. –

+0

Sì, questo è probabilmente il caso. E come dice Chris nel commento alla domanda, forse è legacy - l'enumerazione viene aggiunta in seguito, ma la capacità di #ifdef su di essi è ancora necessaria. – GrahamW

+5

+1: questo trucco è [descritto in 'gcc''s' cpp' documentation] (http://gcc.gnu.org/onlinedocs/gcc-4.6.2/cpp/Self_002dReferential-Macros.html#Self_002dReferential-Macros) come utile utilizzo di macro autoreferenziali. –

11

La mia ipotesi (non analizzata) è che le istruzioni #define consentono test condizionali per verificare se la costante è stata definita.

Ad esempio:

#ifdef DT_UNKNOWN 
    // do something 
#endif 
24

Oltre alle altre risposte che sono molto buoni - vorrei andare con loro per la ragione principale - il compilatore potrebbe generare avvisi o errori se si tenta di ridefinire DT_UNKNOWN.

0

Ho usato -E e -dD argomenti (e anche -fdump-tree-all) in gcc per vedere l'uscita del preprocessore e hanno trovato nulla di utile. Quindi immagino che questo codice non abbia alcuna funzionalità se non quella di visualizzare i nomi simbolici durante il debug usando un debugger come gdb.

7

Penso che la risposta di Luchian Grigore fosse corretta.

Codice senza definisce:

#include <stdio.h> 

// Defined somewhere in headers 
#define DT_UNKNOWN 0 

enum 
{ 
    DT_UNKNOWN = 0, 
    DT_FIFO = 1, 
}; 

int main(int argc, char **argv) 
{ 
    printf("DT_UNKNOWN is %d\n", DT_UNKNOWN); 
    return 0; 
} 

Dall'uscita del compilatore non è chiaro il motivo per cui qualche linea di codice all'interno enum non vuole costruire:

[email protected]:~/tmp$ gcc -Wall ./main.c 
./main.c:7: error: expected identifier before numeric constant 

Dopo aggiungiamo tali definisce:

#include <stdio.h> 

// Defined somewhere in headers 
#define DT_UNKNOWN 0 

enum 
{ 
    DT_UNKNOWN = 0, 
    # define DT_UNKNOWN DT_UNKNOWN 
    DT_FIFO = 1, 
    # define DT_FIFO DT_FIFO 
}; 

int main(int argc, char **argv) 
{ 
    printf("DT_UNKNOWN is %d\n", DT_UNKNOWN); 
    return 0; 
} 

Il compilatore ci dice che DT_UNKNOWN è ridefinito e un luogo dove viene ridefinito:

[email protected]:~/tmp$ gcc -Wall ./main2.c 
./main2.c:7: error: expected identifier before numeric constant 
./main2.c:8:1: warning: "DT_UNKNOWN" redefined 
./main2.c:3:1: warning: this is the location of the previous definition