C n'a pas de type booléen intégré. Quelle est la meilleure façon de les utiliser en C?
Du meilleur au pire:
Option 1 (C99)
#include <stdbool.h>
Option 2
typedef enum { false, true } bool;
Option 3
typedef int bool;
enum { false, true };
Option 4
typedef int bool;
#define true 1
#define false 0
Si vous êtes indécis, allez avec # 1!
Quelques réflexions sur les booléens en C:
Je suis assez vieux pour utiliser Plain int
s comme type booléen sans définition de type, définition ou énumération spéciale pour les valeurs vrai/faux. Si vous suivez ma suggestion ci-dessous pour ne jamais comparer avec les constantes booléennes, vous devez uniquement utiliser 0/1 pour initialiser les indicateurs de toute façon. Cependant, une telle approche peut être jugée trop réactionnaire en ces temps modernes. Dans ce cas, il faut absolument utiliser <stdbool.h>
car il a au moins l'avantage d'être standardisé.
Quel que soit le nom des 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 en fait être lus de manière raisonnable et compréhensible.
Donnez à vos variables booléennes des noms positifs, c'est-à-dire full
au lieu de notfull
. Ce dernier conduit à un code difficile à lire facilement. Comparer
if (full) ...
if (!full) ...
avec
if (!notfull) ...
if (notfull) ...
Les deux paires précédentes lisent naturellement, alors que !notfull
est difficile à lire même en l'état, et devient bien pire dans des expressions booléennes plus complexes.
Les arguments booléens devraient généralement être évités. Considérons une fonction définie comme ceci
void foo(bool option) { ... }
Dans le corps de la fonction, la signification de l’argument est très claire, car elle porte un nom pratique et, espérons-le, significatif. Mais, les sites d'appels ressemblent à
foo(TRUE);
foo(FALSE):
Ici, il est essentiellement impossible de déterminer le sens du paramètre sans toujours regarder la définition ou la déclaration de la fonction, et la situation empire dès que vous ajoutez encore plus de paramètres 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 approfondir la définition de foo
.
Un booléen en C est un entier: zéro pour faux et non nul pour vrai.
Voir aussi Type de données booléennes, 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 seule valeur, mais qu'un vrai logique peut avoir plusieurs valeurs, mais la technique définit true comme étant ce que le compilateur utilisera pour l'inverse de faux.
Cela prend en charge le problème de quelqu'un codant quelque chose qui se résumerait à ceci:
if (true == !false)
Je pense que nous conviendrons tous que ce n'est pas une bonne pratique, mais pour le coût ponctuel de faire "true =! False", nous éliminons ce problème.
[EDIT] En fin de compte, j'ai utilisé:
typedef enum { myfalse = 0, mytrue = !myfalse } mybool;
pour éviter une collision de noms avec d’autres schémas définissant true
et false
. Mais le concept reste 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 un 0, puis le second (le plus à gauche)! convertit le 0 en une valeur myfalse
. Je vais laisser cela au lecteur de convertir un entier zéro.
Si vous utilisez un compilateur C99, celui-ci prend en charge les types bool:
#include <stdbool.h>
int main()
{
bool b = false;
b = true;
}
typedef enum {
false = 0,
true
} t_bool;
C a un type booléen: bool (au moins depuis 10 (!) Ans)
Inclure stdbool.h et true/false fonctionneront comme prévu.
Tout ce qui est différent de zéro est évalué à vrai dans les opérations booléennes, vous pouvez donc simplement
#define TRUE 1
#define FALSE 0
et utiliser les constantes.
@Thomas Matthews: les expressions conditionnelles sont considérées vraies si elles sont non nulles, mais le standard C exige que les opérateurs logiques renvoient eux-mêmes 0 ou 1.
@Tom: #define TRUE! FALSE est mauvais et complètement inutile. Si le fichier d'en-tête pénètre dans le code C++ compilé, des problèmes peuvent survenir:
void foo(bool flag);
...
int flag = TRUE;
foo(flag);
Certains compilateurs généreront un avertissement concernant la conversion int => bool. Parfois, les gens évitent cela en faisant:
foo(flag == TRUE);
pour forcer l'expression à être un bool C++. Mais si vous définissez VRAI! FAUX, vous vous retrouvez avec:
foo(flag == !0);
qui finit par faire une comparaison int-to-bool qui peut déclencher l'avertissement de toute façon.
Vous pouvez utiliser un caractère ou un autre conteneur de petit nombre.
Pseudo-code
#define TRUE 1
#define FALSE 0
char bValue = TRUE;
C'est ça:
#define TRUE 1
#define FALSE 0
Juste un complément à d’autres réponses et quelques éclaircissements, si vous êtes autorisé à utiliser C99.
+-------+----------------+-------------------------+--------------------+
| Name | Characteristic | Dependence in stdbool.h | Value |
+-------+----------------+-------------------------+--------------------+
| _Bool | Native type | Don't need header | |
+-------+----------------+-------------------------+--------------------+
| bool | Macro | Yes | Translate to _Bool |
+-------+----------------+-------------------------+--------------------+
| true | Macro | Yes | Translate to 1 |
+-------+----------------+-------------------------+--------------------+
| false | Macro | Yes | Translate to 0 |
+-------+----------------+-------------------------+--------------------+
Certaines de mes préférences:
_Bool
ou bool
? Les deux vont bien, mais bool
est plus beau que le mot clé _Bool
.bool
et _Bool
sont: false
ou true
. Assigner 0
ou 1
au lieu de false
ou true
est valide, mais il est plus difficile de lire et de comprendre le flux logique.Quelques informations de la norme:
_Bool
n'est PAS unsigned int
, mais fait partie du groupe types d'entiers non signés . Il est assez grand pour contenir les valeurs 0
ou 1
.bool
true
et false
mais ce n’est certainement pas une bonne idée. Cette capacité est considérée comme obsolète et sera supprimée à l'avenir._Bool
ou bool
, si la valeur scalar est égale à 0
ou se compare à 0
be 0
, sinon le résultat est 1
: _Bool x = 9;
9
est converti en 1
lorsqu'il est attribué à x
._Bool
est 1 octet (8 bits), le programmeur est généralement tenté d'essayer d'utiliser les autres bits, mais n'est pas recommandé, car la seule garantie donnée est qu'un seul bit est utilisé pour stocker des données, pas comme le type char
qui a 8 bits disponibles.Vous pouvez utiliser _Bool, mais la valeur de retour doit être un entier (1 pour true, 0 pour false). Cependant, il est recommandé d'inclure et d'utiliser bool comme en C++, comme indiqué dans cette réponse de forum daniweb , ainsi que cette réponse , de cette autre question de stackoverflow:
_Bool: le type booléen de C99. L'utilisation directe de _Bool n'est recommandée que si vous conservez du code hérité qui définit déjà des macros pour bool, true ou false. Sinon, ces macros sont normalisées dans l'en-tête. Incluez cet en-tête et vous pouvez utiliser bool comme vous le feriez en C++.