Usando valori booleani in C

C non ha alcun tipo booleano incorporato. Qual è il modo migliore per usarli in C?

opzione 1

typedef int bool; #define true 1 #define false 0 

opzione 2

 typedef int bool; enum { false, true }; 

Opzione 3

 typedef enum { false, true } bool; 

Opzione 4 (C99)

 #include  

Spiegazione

  • Le opzioni 1, 2 e 3 avranno in pratica lo stesso identico comportamento. # 2 e # 3 non usano #defines però, che a mio parere è migliore.
  • L’opzione 4 funzionerà solo se si utilizza C99 ed è il “modo standard” per farlo. Scegli questo se ansible.

Se sei indeciso, vai con # 3!

Alcune riflessioni sui booleani in C:

Sono abbastanza vecchio da usare solo int s semplice come il mio tipo booleano senza typedef o definizioni speciali o enumerazioni per valori vero / falso. Se segui il mio suggerimento qui di seguito per non confrontare mai le costanti booleane, allora devi solo usare 0/1 per inizializzare le bandiere comunque. Tuttavia, un tale approccio può essere considerato troppo reazionario in questi tempi moderni. In tal caso, si dovrebbe usare sicuramente poiché almeno ha il vantaggio di essere standardizzato.

Qualunque siano le costanti booleane chiamate, usale solo per l’inizializzazione. Mai e poi mai scrivere qualcosa del genere

 if (ready == TRUE) ... while (empty == FALSE) ... 

Questi possono sempre essere sostituiti dal più chiaro

 if (ready) ... while (!empty) ... 

Nota che questi possono essere letti in modo ragionevole e comprensibile a voce alta.

Dai alle tue variabili booleane nomi positivi, cioè full invece che notfull . Quest’ultimo porta a un codice che è difficile da leggere facilmente. Confrontare

 if (full) ... if (!full) ... 

con

 if (!notfull) ... if (notfull) ... 

Entrambe le coppie precedenti leggono naturalmente, mentre !notfull è scomodo da leggere anche così com’è, e diventa molto peggio in espressioni booleane più complesse.

Gli argomenti booleani dovrebbero essere generalmente evitati. Considera una funzione definita in questo modo

 void foo(bool option) { ... } 

All’interno del corpo della funzione, è molto chiaro che cosa significa l’argomento poiché ha un nome conveniente e, si spera, significativo. Ma i siti di chiamata sembrano

 foo(TRUE); foo(FALSE): 

Qui, è praticamente imansible dire cosa significhi il parametro senza guardare sempre la definizione o la dichiarazione della funzione, e diventa molto peggio se si aggiungono ancora più parametri booleani. Suggerisco sia

 typedef enum { OPT_ON, OPT_OFF } foo_option; void foo(foo_option option); 

o

 #define OPT_ON true #define OPT_OFF false void foo(bool option) { ... } 

In entrambi i casi, il sito di chiamata ora sembra

 foo(OPT_ON); foo(OPT_OFF); 

che il lettore ha almeno una possibilità di comprendere senza ricostituire la definizione di foo .

Un booleano in C è un numero intero: zero per falso e non zero per vero.

Vedi anche il tipo di dati booleani , sezione C, C ++, Objective-C, AWK .

Ecco la versione che ho usato:

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

Perché falso ha solo un valore, ma un vero logico può avere molti valori, ma la tecnica imposta true come ciò che il compilatore userà per il contrario di false.

Questo si prende cura del problema di qualcuno che codifica qualcosa che potrebbe venire a questo:

 if (true == !false) 

Penso che saremmo tutti d’accordo sul fatto che non è una buona pratica, ma per il costo una tantum di “true =! False” eliminiamo quel problema.

[EDIT] Alla fine ho usato:

 typedef enum { myfalse = 0, mytrue = !myfalse } mybool; 

per evitare la collisione del nome con altri schemi che stavano definendo true e false . Ma il concetto rimane lo stesso.

[MODIFICA] Per mostrare la conversione del numero intero in booleano:

 mybool somebool; int someint = 5; somebool = !!someint; 

Il primo (più giusto)! converte il numero intero non zero in uno 0, quindi il secondo (più sinistro)! converte lo 0 in un valore myfalse . Lascerò come esercizio per il lettore convertire un numero intero zero.

Se stai usando un compilatore C99 ha un supporto integrato per i tipi di bool:

 #include  int main() { bool b = false; b = true; } 

http://en.wikipedia.org/wiki/Boolean_data_type

 typedef enum { false = 0, true } t_bool; 

C ha un tipo booleano: bool (almeno per gli ultimi 10 (!) Anni)

Includere stdbool.h e true / false funzioneranno come previsto.

Qualsiasi cosa diversa da zero viene valutata come vera nelle operazioni booleane, quindi potresti semplicemente

 #define TRUE 1 #define FALSE 0 

e usare le costanti.

Cominciando dall’inizio. C, cioè ISO / IEC 9899 ha avuto un tipo booleano per 19 anni . Questo è il tempo più lungo della durata prevista della carriera di programmazione C con parti amatoriali / accademiche / professionali combinate quando si visita questa domanda . Il mio supera quello di forse 1-2 anni. Tuttavia, durante il tempo in cui un lettore medio ha imparato qualcosa su C, C ha effettivamente avuto il tipo di dati booleani .

Per il tipo di dati, #include e usa true , false e bool . Oppure non includerlo e utilizzare invece _True , _False e _Bool .


Ci sono vari consigli pericolosi in questa discussione di risposta. Li affronterò:

 typedef int bool; #define true 1 #define false 0 

Questo è no-no, perché un lettore casuale – che ha imparato C in questi 19 anni – si aspetterebbe che il bool riferisca al tipo di dati bool effettivo e si comporterebbe allo stesso modo, ma non lo fa! Per esempio

 double a = ...; bool b = a; 

Con C99 bool / _Bool , b sarebbe impostato su false iff a era zero e true altrimenti. Con typedef in posto, il double verrebbe convertito in int – se il valore del double non è nell’intervallo per int int, il comportamento non è definito .

Naturalmente vale lo stesso per se true e false sono stati dichiarati in un enum .

Ciò che è ancora più pericoloso è la dichiarazione

 typedef enum bool { false, true } bool; 

perché ora tutti i valori oltre a 1 e 0 non sono validi e se tale valore dovesse essere assegnato a una variabile di quel tipo, il comportamento sarebbe del tutto indefinito .

Quindi se non puoi usare C99 per qualche motivo inspiegabile, per le variabili booleane devi usare:

  • digita int e valori 0 e 1 as-is ; e fare con attenzione le conversioni del dominio da qualsiasi altro valore a questi con doppia negazione !!
  • o se insisti che non ricordi che 0 è falsa e non-zero, usa almeno maiuscole in modo che non si confondano con i concetti di C99: BOOL , TRUE e FALSE !

@ Thomas Matthews: le espressioni condizionali sono considerate vere se non sono zero, ma lo standard C richiede che gli operatori logici restituiscano 0 o 1.

@Tom: #define VERO! FALSE è cattivo ed è completamente inutile. Se il file di intestazione si inserisce nel codice C ++ compilato, può causare problemi:

 void foo(bool flag); ... int flag = TRUE; foo(flag); 

Alcuni compilatori genereranno un avvertimento circa la conversione int => bool. A volte le persone evitano questo facendo:

 foo(flag == TRUE); 

per forzare l’espressione ad essere un booster in C ++. Ma se #define VERO! FALSO, finisci con:

 foo(flag == !0); 

che finisce per fare un confronto int-to-bool che può innescare comunque l’avvertimento.

È ansible utilizzare un carattere o un altro contenitore di numero piccolo per esso.

pseduo

 #define TRUE 1 #define FALSE 0 char bValue = TRUE; 

È questo:

 #define TRUE 1 #define FALSE 0 

Puoi semplicemente usare la direttiva #define come segue:

 #define TRUE 1 #define FALSE 0 #define NOT(arg) (arg == TRUE)? FALSE : TRUE typedef int bool; 

E usare come segue:

 bool isVisible = FALSE; bool isWorking = TRUE; isVisible = NOT(isVisible); 

e così via