Utiliser des valeurs booléennes en C

C n’a pas de type booléen intégré. Quelle est la meilleure façon de les utiliser en C?

Option 1

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

Option 2

 typedef int bool; enum { false, true }; 

Option 3

 typedef enum { false, true } bool; 

Option 4 (C99)

 #include  

Explication

  • Les options 1, 2 et 3 auront en pratique le même comportement identique. # 2 et # 3 n’utilisent cependant pas #defines, ce qui à mon avis est meilleur.
  • L’option 4 ne fonctionnera que si vous utilisez C99 et que c’est la “manière standard” de le faire. Choisissez ceci si possible.

Si vous êtes indécis, allez avec # 3!

Quelques reflections sur les booléens en C:

Je suis assez vieux pour que j’utilise simplement plain int s comme type booléen sans typedefs ni définitions ou énumérations spéciales pour les valeurs true / false. Si vous suivez ma suggestion ci-dessous sur la comparaison jamais avec les constantes booléennes, il vous suffit d’utiliser 0/1 pour initialiser les indicateurs de toute façon. Cependant, une telle approche peut être jugée trop réactionnaire dans les temps modernes. Dans ce cas, il faut absolument utiliser car il a au moins l’avantage d’être normalisé.

Quelles que soient les constantes booléennes, utilisez-les uniquement pour l’initialisation. Ne jamais écrire quelque chose comme

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

Ceux-ci peuvent toujours être remplacés par le plus clair

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

Notez que ceux-ci peuvent être raisonnablement et raisonnablement compréhensibles.

Donnez à vos variables booléennes des noms positifs, c.- fullnotfull . notfull au lieu de notfull . Ce dernier conduit à un code difficile à lire facilement. Comparer

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

avec

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

Les deux premières paires lisent naturellement, tandis que !notfull est difficile à lire même si, et devient bien pire dans les expressions booléennes plus complexes.

Les arguments booléens doivent généralement être évités. Considérons une fonction définie comme ceci

 void foo(bool option) { ... } 

Dans le corps de la fonction, il est très clair ce que signifie l’argument, car il a un nom pratique et, espérons-le, significatif. Mais, les sites d’appel ressemblent à

 foo(TRUE); foo(FALSE): 

Ici, il est essentiellement impossible de dire ce que signifie le paramètre sans toujours regarder la définition ou la déclaration de la fonction, et cela devient bien pire dès que vous ajoutez encore plus de parameters booléens. Je suggère soit

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

ou

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

Dans les deux cas, le site d’appel ressemble maintenant à

 foo(OPT_ON); foo(OPT_OFF); 

que le lecteur a au moins une chance de comprendre sans chercher à définir le foo .

Un booléen dans C est un entier: zéro pour faux et non nul pour vrai.

Voir aussi Type de données booléen , section C, C ++, Objective-C, AWK .

Voici la version que j’ai utilisée:

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

Parce que false n’a qu’une valeur, mais qu’un true logique peut avoir plusieurs valeurs, mais la technique définit true comme étant ce que le compilateur utilisera pour le contraire de false.

Cela prend en compte le problème de quelqu’un qui code quelque chose qui se résume à ceci:

 if (true == !false) 

Je pense que nous serions tous d’accord pour dire que ce n’est pas une bonne pratique, mais pour le coût ponctuel de «true =! False», nous éliminons ce problème.

[EDIT] Finalement, j’ai utilisé:

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

pour éviter la collision de noms avec d’autres schémas qui définissaient true et false . Mais le concept rest le même.

[EDIT] Pour afficher la conversion d’un entier en booléen:

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

Le premier (le plus à droite)! convertit le nombre entier non nul en 0, puis le second (le plus à gauche)! convertit le 0 en valeur myfalse . Je le laisserai comme exercice pour que le lecteur convertisse un nombre entier de zéro.

Si vous utilisez un compilateur C99, il prend en charge les types de 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 a un type booléen: bool (du moins pour les 10 dernières années!)

Inclure stdbool.h et true / false fonctionnera comme prévu.

Tout ce qui est différent de zéro est évalué à true dans les opérations booléennes.

 #define TRUE 1 #define FALSE 0 

et utilisez les constantes.

Les premières choses d’abord C, c.-à-d. ISO / IEC 9899 a un type booléen depuis 19 ans maintenant . C’est beaucoup plus de temps que la durée prévue de la carrière de programmation en C avec les parties amateur / universitaire / professionnel combinées lors de la visite de cette question . Le mien surpasse ce chiffre à un ou deux ans seulement. Cependant, pendant le temps où un lecteur moyen a appris quelque chose sur C, C a effectivement eu le type de données booléen .

Pour le type de données, #include , et utilisez true , false et bool . Ou ne l’incluez pas et utilisez _True , _False et _Bool .


Il y a divers conseils dangereux dans ce fil de réponse. Je vais les aborder:

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

C’est non-non, car un lecteur occasionnel – qui a appris C en 19 ans – s’attendrait à ce que bool fasse référence au type de données bool réel et se comporte de la même manière, mais ce n’est pas le cas! Par exemple

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

Avec C99 bool / _Bool , b serait mis à false ssi était nul, et true cas contraire. Avec le typedef en place, le double sera forcé dans un int – si la valeur du double n’est pas dans la plage pour int int, le comportement est indéfini .

Naturellement, il en va de même si true et false étaient déclarés dans un enum .

Ce qui est encore plus dangereux est de déclarer

 typedef enum bool { false, true } bool; 

car maintenant toutes les valeurs autres que 1 et 0 sont invalides et si une telle valeur est affectée à une variable de ce type, le comportement sera totalement indéfini .

Par conséquent, si vous ne pouvez pas utiliser C99 pour une raison inexplicable, pour les variables booléennes, vous devez utiliser:

  • tapez int et les valeurs 0 et 1 telles quelles ; et faites soigneusement des conversions de domaine de toute autre valeur à celles-ci avec double négation !!
  • ou si vous insistez, vous ne vous souvenez pas que 0 est faux et non nul, utilisez au moins des majuscules pour ne pas les confondre avec les concepts C99: BOOL , TRUE et FALSE !

@ Thomas Matthews: Les expressions conditionnelles sont considérées comme vraies si elles sont non nulles, mais le standard C exige que les opérateurs logiques eux-mêmes renvoient 0 ou 1.

@Tom: #define TRUE! FALSE est mauvais et complètement inutile. Si le fichier d’en-tête est intégré au code C ++ compilé, cela peut entraîner des problèmes:

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

Certains compilateurs généreront un avertissement sur la conversion int => bool. Parfois, les gens évitent cela en faisant:

 foo(flag == TRUE); 

forcer l’expression à être un C ++ bool. Mais si vous #define TRUE! FALSE, vous vous retrouvez avec:

 foo(flag == !0); 

ce qui finit par faire une comparaison int-to-bool qui peut déclencher l’avertissement quand même.

Vous pouvez utiliser un caractère ou un autre conteneur de petit nombre.

Pseduo

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

C’est ça:

 #define TRUE 1 #define FALSE 0 

Vous pouvez simplement utiliser la directive #define comme suit:

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

Et utiliser comme suit:

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

etc