2015-10-25 16 views
11

Quindi normalmente le enum sono per dichiarare un gruppo di "numeri interi costanti" come un altro tipo, che rappresenta qualcosa. Per esempio.Questa dichiarazione enum è conforme allo standard?

enum Color {RED=0, BLUE, YELLOW}; 

Questo è chiaro. Ma di recente mi sono incontrato seguendo il codice. Questo era in un compilatore per sistemi embedded.

enum State {DISABLED=0, ENABLED=!DISABLED}; 

E ha funzionato bene. Si è comportato come un tipo booleano. La mia domanda è, che (questa sintassi) è conforme ANSI?

Se è aderente allo standard, allora perché i compilatori definiscono internamente qualcosa come _Bool per la rappresentazione booleana e poi in stdbool.h (per il linguaggio C) che fanno:

#define bool _Bool 
... // here goes definitions of true and false 

invece di

enum bool {false=0, true=!false}; 

Quale è molto più pulito?

+0

conforme ANSI? Questa è una frase che non ho sentito da un po '. –

+0

@DawidPi C e C++ sono lingue diverse, e problemi delicati come questo praticamente non ottengono mai una buona risposta che copra entrambe le lingue allo stesso tempo. Se vuoi davvero conoscere entrambe le lingue, per favore chiedi loro come domande separate. – hvd

+0

@AlanStokes Se hai un problema con una modifica che ho fatto esplicitamente spiegando nei commenti, mi sembra abbastanza scortese di ripristinarlo senza alcun commento. Non voglio entrare in una guerra di chiusura su questo, ma per quanto mi riguarda, questa domanda era troppo ampia nel suo stato originale, e se hai intenzione di ostacolare i tentativi di metterlo in forma, bene , Voterò solo per chiudere. (Il che ovviamente non significa affatto che finirà per chiudere). – hvd

risposta

3

Sì, la dichiarazione è perfettamente valida e portabile sia in C che in C++.

Sia C e C++, questo:

enum State {DISABLED=0, ENABLED=!DISABLED}; 

è esattamente equivalente a questo:

enum State {DISABLED=0, ENABLED=1}; 

ea tal:

enum State {DISABLED, ENABLED}; 

ma per sottilmente diverse ragioni.

In C, il ! operatore unario produce un risultato di tipo int, con valore sia 0 (se l'operando è diverso da 0) o 1 (se l'operando è uguale a 0). !x è equivalente a x == 0. (Qualsiasi valore diverso da zero viene considerato true se utilizzato come condizione, ma gli operatori ! e ==, tra gli altri, producono sempre un risultato esattamente uguale a 0 o 1). Le costanti di enumerazione sono sempre di tipo int; se viene specificato un valore, viene convertito in int se necessario.

(C tipo _Bool aggiunto nello standard 1999 ma tutti gli operatori che producono logicamente valori "booleani" tuttavia risultati di tipo int.)

In C++, il risultato della ! operatore unario è di tipo bool . Il risultato è false o true dove l'operatore ! di C restituisce 0 o 1, rispettivamente. Come in C, se viene specificato un valore, viene convertito secondo necessità; i valori boolfalse e true convertiti in 0 e 1, rispettivamente.

In C, le costanti di enumerazione sono sempre di tipo int. In C++, sono del tipo di enumerazione, in questo caso enum State.

Il riferimento a una costante di enumerazione precedente all'interno della stessa dichiarazione di tipo è legale. Ogni costante di enumerazione diventa visibile dopo la sua dichiarazione.

Per quanto riguarda qualcosa di simile:

enum bool { false = 0, true = !false); 

essere più chiaro di

enum bool { false = 0, true = 1 }; 

(in C, sarebbe illegale in C++), ho rispettosamente in disaccordo. La costante 1 è perfettamente chiara per chiunque abbia familiarità con C. Riscrivendolo come !false non è utile.Infatti, quando <stdbool.h> non è disponibile (qualcosa che è raro in questi giorni), ho usato:

typedef enum { false, true } bool; 

Il fatto che false e true sarà dato loro valori corretti è IMHO sufficientemente evidente.

Per quanto riguarda il motivo per cui C99 non ha utilizzato una definizione simile a enum, ho il sospetto che sia perché ogni tipo di enumerazione è compatibile con un tipo di intero definito dall'implementazione. (Per gcc, di solito è unsigned int o int.) Il comitato voleva che _Bool fosse un tipo distinto con un grado di conversione inferiore a qualsiasi altro tipo intero. (E non potevano rendere bool una parola chiave senza rompere il codice esistente.)

3

Secondo il C standard (6.2.1 Scopes di identificatori)

Ogni costante enumerazione ha portata che inizia subito dopo il aspetto della sua enumerator definire in un elenco enumeratore

Il lo stesso è valido in C++ (3.3.2 Punto di dichiarazione)

5 Il punto di dichiarazione per un enumeratore è immediatamente dopo il suo enumerator alta definizione. [Esempio:

const int x = 12; 
{ enum { x = x }; } 

Qui, l'enumeratore x viene inizializzata con il valore della costante x, vale a dire 12. -end esempio]

Così si può utilizzare enumeratori già definiti nelle definizioni dei successivi enumeratori in un'enumerazione.

Per quanto riguarda il tipo C _Bool allora è apparso in C 99. Prima di questo standard non sono utilizzati sia costanti manifeste o enumerazioni in C.

Non ha senso definire un'enumerazione come questo

enum bool {false=0, true!=false}; 

perché il tipo _Bool è già dispone di due valori 0 e 1.

6

Sì, questo è standard-compliant.

!DISABLED è una valida costante espressione, che è tutto ciò che è richiesto per un valore enum.

enum State {DISABLED=0, ENABLED= (!DISABLED)}; 
//        ^^^^^^^^^^^ 

Al punto in cui viene fatto riferimento DISABLED, il compilatore conosce il suo valore, in modo che possa calcolare il valore dell'espressione che ne deriva, cioè !DISABLED. È un modo elegante di scrivere ENABLED=1.

+0

E c'è un motivo valido per uno solo scrivere 'ENABLED = 1' (dove anche il' = 1' può essere ridondante a meno che tu non voglia renderlo "clear") – Jack

+0

"È un modo elegante di scrivere' ENABLED = 1' non è corretto. Dato che un enum è in realtà una dimensione "int" e che "! DISABLED" non significa aggiungere 1 ma piuttosto "non 0", che viene direttamente inserito nel codice ogni volta che il compilatore vede "ABILITATO" – user3629249

+0

@ user3629249: Cosa? – Ryan

Problemi correlati