web-dev-qa-db-fra.com

Utilisation de 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?

584
neuromancer

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

Explication

  • L'option 1 ne fonctionnera que si vous utilisez C99 et que c'est la "méthode standard" pour le faire. Choisissez ceci si possible.
  • Les options 2, 3 et 4 auront pratiquement le même comportement. Les n ° 2 et n ° 3 n'utilisent pas #defines cependant, ce qui à mon avis est meilleur.

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

911
Andreas Bonini

Quelques réflexions sur les booléens en C:

Je suis assez vieux pour utiliser Plain ints 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.

210
Dale Hagglund

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 .

79
Fortega

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. 

64
Michael Potter

Si vous utilisez un compilateur C99, celui-ci prend en charge les types bool:

#include <stdbool.h>
int main()
{
  bool b = false;
  b = true;
}

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

41
Gary Willoughby
typedef enum {
    false = 0,
    true
} t_bool;
17
mouviciel

C a un type booléen: bool (au moins depuis 10 (!) Ans)

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

11
dmeister

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.

8
ggambett

@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.

1
jamesdlin

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

Pseudo-code

#define TRUE  1
#define FALSE 0

char bValue = TRUE;
0
Filip Ekberg

C'est ça:

#define TRUE 1
#define FALSE 0
0
RngTng

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.
  • Les valeurs acceptées pour 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.
  • NE PAS FAIRE, mais oui, vous pouvez redéfinir booltrue 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.
  • Affectation d'un type scalaire (types arithmétiques et types de pointeur) à _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.
0
Undefined Behavior

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++.

0
Lokian