Puis-je supposer (bool) true == (int) 1 pour n'importe quel compilateur C ++?

118

Puis-je supposer (bool)true == (int)1pour n'importe quel compilateur C ++?

Petruza
la source
3
Les lancers dans votre question sont redondants, devraient-ils être inversés?
GManNickG
9
Il ne veut pas qu'ils soient des castes, il veut direbool t = true; int n = 1; if (t == n) {...} ;
egrunin
7
@egrunin: Eh, mais true est un bool et 1 est un int de toute façon. :)
GManNickG
1
Bon, je voulais indiquer le type des valeurs.
Petruza
2
(int) trueest 1une valeur entière, mais quelque chose comme if (pointer)passe par la partie then if pointer != 0. La seule chose que vous pouvez supposer comme vraie est que false == 0, et true != 0(et trues'évalue 1lors du casting int)
Luis Colorado

Réponses:

134

Oui. Les moulages sont redondants. Dans votre expression:

true == 1

La promotion intégrale s'applique et la valeur booléenne sera promue à un int et cette promotion doit donner 1.

Référence: 4.7 [conv.integral] / 4: Si le type de source est bool... trueest converti en un.

CB Bailey
la source
9
@Joshua: trueest un mot-clé défini par la langue. Il ne peut pas être redéfini par une bibliothèque. #defineLes utilisateurs ne sont pas autorisés à redéfinir les mots-clés.
jalf
21
@jalf: les # define sont en effet autorisés à définir des mots-clés système. La phase de pré-traitement de la compilation C est purement textuelle et ne connaît ni les mots-clés ni la syntaxe C en général. Néanmoins, il est, bien sûr, presque toujours une mauvaise idée de redéfinir les mots-clés de la langue.
Dale Hagglund
2
@jalf. Ils ne sont pas? Voir gcc.gnu.org/onlinedocs/cpp/Macros.html , et au moins une des participations au concours international de code C obscurci, qui demandait une fois "Quand cela whilene prend-il pas un certain temps?" (Réponse: quand il faut deux paramètres, parce qu'alors cette entrée l'avait #definedfait printf.)
Ken Bloom
3
C99, §6.10.1 / 1 dit: "L'expression qui contrôle l'inclusion conditionnelle doit être une expression constante entière sauf que: elle ne doit pas contenir de transtypage; les identifiants (y compris ceux lexiquement identiques aux mots-clés) sont interprétés comme décrit ci-dessous;" Bien que cela ne soit pas indiqué comme une autorisation directe, cela envisage clairement la possibilité d'une macro "lexicalement identique" à un mot-clé.
Jerry Coffin
2
Oh, et #defines sont autorisés à redéfinir les mots-clés. C ++ 1x a causé trop de problèmes avec ses nouveaux mots clés et cette exigence a dû être supprimée.
Joshua
18

La réponse de Charles Bailey est correcte. Le libellé exact de la norme C ++ est (§4.7 / 4): "Si le type source est booléen, la valeur false est convertie en zéro et la valeur true est convertie en un."

Edit: Je vois qu'il a également ajouté la référence - je supprimerai ceci sous peu, si je ne suis pas distrait et que j'oublie ...

Edit2: Là encore, il est probablement intéressant de noter que si les valeurs booléennes elles-mêmes se convertissent toujours en zéro ou un, un certain nombre de fonctions (en particulier de la bibliothèque standard C) renvoient des valeurs qui sont "fondamentalement booléennes", mais représentées par des ints qui sont normalement, il suffit d'être zéro pour indiquer faux ou différent de zéro pour indiquer vrai. Par exemple, les fonctions is * de <ctype.h>ne nécessitent que zéro ou différent de zéro, pas nécessairement zéro ou un.

Si vous boolconvertissez cela en , zéro sera converti en faux et différent de zéro en vrai (comme vous vous en doutez).

Jerry Coffin
la source
9

Selon la norme, vous devriez être prudent avec cette hypothèse. Le booltype C ++ a deux valeurs - trueetfalse avec les valeurs correspondantes 1 et 0.

La chose à surveiller est de mélanger des boolexpressions et des variables avec des BOOLexpressions et des variables. Ce dernier est défini comme FALSE = 0et TRUE != FALSE, ce qui signifie assez souvent en pratique que toute valeur différente de 0 est considéréeTRUE .

De nombreux compilateurs modernes émettront en fait un avertissement pour tout code qui essaie implicitement d'effectuer un cast de BOOLvers boolsi la BOOLvaleur est différente de 0 ou 1.

Franci Penov
la source
3

J'ai trouvé que différents compilateurs renvoient des résultats différents sur true. J'ai également trouvé qu'il vaut presque toujours mieux comparer un booléen à un bool au lieu d'un int. Ces ints ont tendance à changer de valeur au fil du temps au fur et à mesure que votre programme évolue et si vous supposez que vrai est 1, vous pouvez être mordu par un changement sans rapport ailleurs dans votre code.

Michael Dorgan
la source
3
C'est une réponse incorrecte pour C ++, tout comme trueun mot clé de langage avec un comportement défini. Si vous faites référence à une macro généralement définie comme TRUE, c'est correct.
David Thornley
1
Peut-être que mon expérience était avec les compilateurs C - j'ai passé beaucoup de temps avec eux au fil des ans. Mon point sur l'utilisation directe d'expressions mathématiques dans les déclarations if tient cependant. Nous avions du code qui voyait si un décalage de bits était non nul dans un if, alors quelqu'un d'autre prenait cette même valeur non nulle et supposait que c'était 1 et faisait sauter des choses. Une simple conversion en true / 1 aurait empêché cela.
Michael Dorgan
J'ai moi aussi vu des comportements de ce genre. Certes, la dernière fois que je l'ai vu, c'était vers 1999. J'utilisais GCC. Le langage était C. Pourtant, j'ai effectivement vu un tel comportement.
thb