Domanda

Qual è la differenza tra l'utilizzo di un'istruzione define e un'istruzione enum in C / C ++ (e c'è qualche differenza nell'usarli con C o C ++)?

Ad esempio, quando si dovrebbe usare

enum {BUFFER = 1234}; 

su

#define BUFFER 1234   
È stato utile?

Soluzione

enum definisce un elemento sintattico.

#define è una direttiva pre-preprocessore, eseguita prima che il compilatore vede il codice e quindi non è un elemento di linguaggio di C stesso.

In genere si preferiscono gli enumerati perché sono sicuri per i tipi e più facilmente individuabili. Le definizioni sono più difficili da individuare e possono avere comportamenti complessi, ad esempio un pezzo di codice può ridefinire un #define creato da un altro. Questo può essere difficile da rintracciare.

Altri suggerimenti

Le istruzioni

?? #define sono gestite dal pre-processore prima che il compilatore riesca a vedere il codice, quindi è sostanzialmente una sostituzione del testo (in realtà è un po 'più intelligente con l'uso di parametri e simili).

Le enumerazioni fanno parte del linguaggio C stesso e presentano i seguenti vantaggi.

1 / Potrebbero avere il tipo e il compilatore può controllarli.

2 / Poiché sono disponibili per il compilatore, le informazioni sui simboli su di essi possono essere passate al debugger, semplificando il debug.

Define è un comando preprocessore, è proprio come fare " sostituire tutto " nel tuo editor, può sostituire una stringa con un'altra e quindi compilare il risultato.

Enum è un caso speciale di tipo, ad esempio se scrivi:

enum ERROR_TYPES
{
   REGULAR_ERR =1,
   OK =0
}

esiste un nuovo tipo chiamato ERROR_TYPES. È vero che REGULAR_ERR cede a 1 ma il casting da questo tipo a int dovrebbe produrre un avviso di casting (se si configura il compilatore su un livello elevato di verbosità).

Sommario: sono entrambi uguali, ma quando si utilizza enum si guadagna il controllo del tipo e usando definisce si sostituiscono semplicemente le stringhe di codice.

Gli enum sono generalmente preferiti a #define ovunque abbia senso usare un enum:

  • I debugger possono mostrarti il ??nome simbolico del valore di un enum (" openType: OpenExisting " ;, piuttosto che " openType: 2 "
  • Ottieni un po 'più di protezione dagli scontri con i nomi, ma non è così male come lo era (la maggior parte dei compilatori mette in guardia circa re #define ition.

La differenza più grande è che puoi usare enum come tipi:

// Yeah, dumb example
enum OpenType {
    OpenExisting,
    OpenOrCreate,
    Truncate
};

void OpenFile(const char* filename, OpenType openType, int bufferSize);

Questo ti dà il controllo del tipo di parametri (non puoi mescolare facilmente OpenType e bufferSize) e semplifica la ricerca di valori validi, rendendo le tue interfacce molto più facili da usare. Alcuni IDE possono persino darti intellisense completamento del codice!

È sempre meglio usare un enum, se possibile. L'uso di un enum fornisce al compilatore maggiori informazioni sul codice sorgente, una definizione del preprocessore non viene mai vista dal compilatore e quindi trasporta meno informazioni.

Per l'implementazione, ad es. un sacco di modalità, usando un enum rende possibile al compilatore di catturare le dichiarazioni mancanti case in uno switch, per esempio.

enum può raggruppare più elementi in una categoria:

enum fruits{ apple=1234, orange=12345};

mentre #define può solo creare costanti non correlate:

#define apple 1234
#define orange 12345

#define è un comando preprocessore, enum è in linguaggio C o C ++.

È sempre meglio usare enum su #define per questo tipo di casi. Una cosa è la sicurezza dei tipi. Un altro è che quando hai una sequenza di valori devi solo dare l'inizio della sequenza nell'enum, gli altri valori ottengono valori consecutivi.

enum {
  ONE = 1,
  TWO,
  THREE,
  FOUR
};

anziché

#define ONE 1
#define TWO 2
#define THREE 3
#define FOUR 4

Come nota a margine, ci sono ancora alcuni casi in cui potresti dover usare #define (in genere per qualche tipo di macro, se devi essere in grado di costruire un identificatore che contiene la costante), ma è un po ' macro magia nera, e molto molto rara per essere la strada da percorrere. Se vai a queste estremità, probabilmente dovresti usare un modello C ++ (ma se sei bloccato con C ...).

Se vuoi solo questa singola costante (diciamo per buffersize), allora non userei un enum, ma un define. Vorrei usare enum per cose come i valori di ritorno (che significano condizioni di errore diverse) e ovunque dovessimo distinguere diversi "tipi". o "casi". In tal caso, possiamo usare un enum per creare un nuovo tipo che possiamo usare nei prototipi di funzioni, ecc., E quindi il compilatore può controllare meglio quel codice.

Oltre a tutto ciò che è già stato scritto, uno ha detto ma non mostrato ed è invece interessante. Per es.

enum action { DO_JUMP, DO_TURNL, DO_TURNR, DO_STOP };
//...
void do_action( enum action anAction, info_t x );

Considerare l'azione come un tipo rende le cose più chiare. Usando define, avresti scritto

void do_action(int anAction, info_t x);

Per i valori delle costanti integrali sono arrivato a preferire enum rispetto a #define . Sembra che non ci siano svantaggi nell'uso di enum (sconto dello svantaggio minuscolo di un po 'più di digitazione), ma hai il vantaggio che enum può essere definito, mentre Gli identificatori #define hanno un ambito globale che trompe tutto.

L'uso di #define di solito non è un problema, ma poiché non ci sono svantaggi per enum , ci vado.

In C ++ generalmente preferisco enum a const int anche se in C ++ un const int può essere usato al posto di un intero letterale valore (diversamente da C) perché enum è portabile su C (che lavoro ancora molto).

Se si dispone di un gruppo di costanti (come "Giorni della settimana") sarebbe preferibile un enumerazione, poiché mostra che sono raggruppati; e, come ha detto Jason, sono sicuri per i tipi. Se è una costante globale (come il numero di versione), è più quello per cui useresti un #define ; sebbene questo sia oggetto di molti dibattiti.

Oltre ai punti positivi sopra elencati, puoi limitare l'ambito degli enum a una classe, struttura o spazio dei nomi. Personalmente, mi piace avere il numero minimo di simboli pertinenti nell'ambito in qualsiasi momento, il che è un altro motivo per usare enum piuttosto che #define.

Un altro vantaggio di un enum su un elenco di definisce è che i compilatori (almeno gcc) possono generare un avviso quando non tutti i valori sono controllati in un'istruzione switch. Ad esempio:

enum {
    STATE_ONE,
    STATE_TWO,
    STATE_THREE
};

...

switch (state) {
case STATE_ONE:
    handle_state_one();
    break;
case STATE_TWO:
    handle_state_two();
    break;
};

Nel codice precedente, il compilatore è in grado di generare un avviso che non tutti i valori dell'enum vengono gestiti nello switch. Se gli stati fossero fatti come # define, non sarebbe così.

gli enum sono più usati per enumerare un qualche tipo di set, come i giorni di una settimana. Se hai bisogno di un solo numero costante, const int (o doppio ecc.) Sarebbe sicuramente migliore di enum. Personalmente non mi piace #define (almeno non per la definizione di alcune costanti) perché non mi dà sicurezza del tipo, ma puoi ovviamente usarlo se ti si addice meglio.

La creazione di un enum crea non solo valori letterali ma anche il tipo che raggruppa questi valori letterali: ciò aggiunge semantica al codice che il compilatore è in grado di controllare.

Inoltre, quando si utilizza un debugger, si ha accesso ai valori dei letterali enum. Questo non è sempre il caso di #define.

Mentre diverse risposte sopra suggeriscono di usare enum per vari motivi, vorrei sottolineare che l'uso di definisce ha un reale vantaggio nello sviluppo di interfacce. Puoi introdurre nuove opzioni e consentire al software di usarle in modo condizionale.

Ad esempio:

    #define OPT_X1 1 /* introduced in version 1 */
    #define OPT_X2 2 /* introduced in version  2 */

Quindi può essere compilato un software che può essere compilato con entrambe le versioni

    #ifdef OPT_X2
    int flags = OPT_X2;
    #else
    int flags = 0;
    #endif

In un'enumerazione questo non è possibile senza un meccanismo di rilevamento delle funzionalità di runtime.

Enum:
1. Generalmente utilizzato per più valori

2. In enum ci sono due cose: uno è name e un altro è value del nome name deve essere distinto ma il valore può essere lo stesso. Se non definiamo il valore, il primo valore del nome enum è 0 secondo, il valore è 1 e così via, a meno che non sia specificato esplicitamente il valore.

3. Possono avere un tipo e un compilatore può digitare controllarli

4. Semplifica il debug

5. Possiamo limitarne l'ambito a una classe.

Definisci:
1. Quando dobbiamo definire un solo valore

2. In genere sostituisce una stringa con un'altra stringa.

3. L'ambito è globale e non possiamo limitarne l'ambito

Nel complesso dobbiamo usare enum

C'è poca differenza. Lo standard C afferma che le enumerazioni hanno tipo integrale e che le costanti di enumerazione sono di tipo int, quindi entrambe possono essere mescolate liberamente con altri tipi integrali, senza errori. (Se, d'altra parte, tale mescolanza fosse vietata senza cast espliciti, un uso giudizioso delle enumerazioni potrebbe rilevare alcuni errori di programmazione.)

Alcuni vantaggi delle enumerazioni sono che i valori numerici vengono assegnati automaticamente, che un debugger può essere in grado di visualizzare i valori simbolici quando vengono esaminate le variabili di enumerazione e che obbediscono all'ambito del blocco. (Un compilatore può anche generare avvisi non fatali quando le enumerazioni sono indiscriminatamente mescolate, poiché farlo può ancora essere considerato cattivo stile anche se non è strettamente illegale.) Uno svantaggio è che il programmatore ha uno scarso controllo su quegli avvisi non fatali; alcuni programmatori inoltre si risentono di non avere il controllo sulle dimensioni delle variabili di enumerazione.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top