Question Utilisation de valeurs booléennes en C


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


526
2017-12-17 12:46


origine


Réponses:


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!


827
2017-12-17 12:49



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

Je suis assez vieux pour utiliser simplement ints comme mon type booléen sans typedefs ou special defined ou enums 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 en ces temps modernes. Dans ce cas, il faut absolument utiliser <stdbool.h> puisqu'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, ie 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 anciens lisent naturellement, tandis que !notfull est maladroit à lire même tel qu'il est, 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) { ... }

À 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 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 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 pour autant déblayer la définition de foo.


190
2017-12-18 04:55



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

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


75
2017-12-17 12:49



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 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] A la fin j'ai utilisé:

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

pour éviter la collision de noms avec d'autres régimes qui définissaient trueet 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 un myfalse valeur. Je vais le laisser comme un exercice pour le lecteur de convertir un entier zéro.


60
2018-05-14 22:31



Si vous utilisez un compilateur C99, il prend en charge les types de booléen:

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

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


35
2017-12-17 14:54



typedef enum {
    false = 0,
    true
} t_bool;

17
2017-12-17 12:51



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.


10
2017-12-17 13:28



Tout ce qui n'est pas nul est évalué à vrai dans les opérations booléennes, donc vous pourriez juste

#define TRUE 1
#define FALSE 0

et utilise les constantes.


8
2017-12-17 12:48



Premières choses d'abord. C, c'est-à-dire ISO / CEI 9899 a un type booléen pour 19 ans maintenant. C'est beaucoup plus long que le attendu durée de la carrière en programmation C avec des parties amateur / académique / professionnel combinées lors de la visite cette question. Le mien surpasse cela de seulement peut-être 1-2 ans. Cependant, pendant le temps qu'un lecteur moyen a appris quelque chose au sujet de C, C a effectivement eu le type de données booléen.

Pour le type de données, #include <stdbool.h>, et utilise true, falseet bool. Ou ne l'incluez pas et utilisez _True, _Falseet _Bool au lieu.


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

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

C'est un non-non, parce qu'un lecteur occasionnel - qui a appris le C au cours de ces 19 années - s'attendrait à ce que bool se réfère à la réel  bool type de données et se comporterait 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 réglé à false  sff  a était zéro, et true autrement. Avec le typedef en place, le double serait contraint à un int - si la valeur du double n'est pas dans la fourchette int int, le le comportement est indéfini.

Naturellement, il en va de même si trueet false ont été déclarés dans un enum.

Qu'est-ce qui est encore plus dangereux déclare

typedef enum bool {
    false, true
} bool;

parce que maintenant toutes les valeurs en outre 1 et 0 ne sont pas valides, et si une telle valeur est affectée à une variable de ce type, le comportement serait totalement indéfini.

Donc sff vous ne pouvez pas utiliser C99 pour une raison inexplicable, pour les variables booléennes que vous devriez utiliser:

  • type int et les valeurs 0et 1  comme si; et effectuez soigneusement les conversions de domaine à partir de toutes les autres valeurs à ceux avec une double négation !!
  • ou si vous insister vous ne vous souvenez pas que 0 est fausse et non nulle, au moins utiliser haut de casse afin qu'ils ne soient pas confondus avec les concepts C99: BOOL, TRUEet FALSE!

4
2018-05-18 16:36



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


1
2017-12-18 04:17