une - variable booléenne c




Utilisation de valeurs booléennes en C (8)

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

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

void foo(bool flag);

...

int flag = TRUE;
foo(flag);

Certains compilateurs vont générer un avertissement à propos de la conversion int => bool. Parfois, les gens évitent cela en faisant:

foo(flag == TRUE);

pour forcer l'expression à être un booléen C ++. Mais si #define TRUE! FALSE, 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.

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


C a un type booléen: bool (au moins pour les 10 dernières années!)

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


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

Je suis assez vieux que j'utilise simplement les int simples comme mon type booléen sans typedefs ou définitions spéciales ou enums pour les valeurs vrai / faux. Si vous suivez ma suggestion ci-dessous de ne jamais comparer avec les constantes booléennes, alors vous avez seulement besoin d'utiliser 0/1 pour initialiser les drapeaux 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é.

Quelles que soient les constantes booléennes appelées, utilisez-les uniquement pour l'initialisation. N'écrivez jamais 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 réellement et raisonnablement être lus à haute voix.

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 lisent naturellement, tandis que !notfull est difficile à lire même s'il est, et devient bien pire dans les 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) { ... }

À l'intérieur du corps de la fonction, il est très clair ce que l'argument signifie puisqu'il a un nom commode et, espérons-le, significatif. Mais, les sites d'appel ressemblent

foo(TRUE);
foo(FALSE):

Ici, il est essentiellement impossible de dire ce que le paramètre signifie sans toujours regarder la définition ou la fonction de la fonction, et cela devient bien pire 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 draguer la définition de foo .




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 une valeur logique true peut avoir plusieurs valeurs, mais la valeur false correspond à ce que le compilateur utilisera pour le contraire de false.

Cela prend en charge 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 faire «vrai = faux», nous éliminons ce problème.

[EDIT] À la fin 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 reste le même.

[EDIT] Pour montrer la conversion d'entier en booléen:

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

Le premier (le plus à droite)! convertit l'entier non nul en un 0, puis le second (le plus à gauche)! convertit le 0 en une valeur myfalse . Je vais le laisser comme un exercice pour le lecteur de convertir un entier zéro.


Vous pouvez utiliser un char, ou un autre petit conteneur de nombres pour cela.

Pseduo

#define TRUE  1
#define FALSE 0

char bValue = TRUE;

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 <stdbool.h>

Explication

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

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





boolean