Je sais qu'en C et C++, lors de la conversion de bools en ints, (int)true == 1
et (int)false == 0
. Je m'interroge sur le casting dans le sens inverse ...
Dans le code ci-dessous, toutes les assertions suivantes sont vraies dans les fichiers .c compilés avec Visual Studio 2013 et Keil µVision 5. Notice (bool)2 == true
.
Que disent les normes C et C++ à propos de la conversion de nombres entiers non nuls, non-un en bools? Ce comportement est-il spécifié? S'il vous plaît inclure des citations.
#include <stdbool.h>
#include <assert.h>
void TestBoolCast(void)
{
int i0 = 0, i1 = 1, i2 = 2;
assert((bool)i0 == false);
assert((bool)i1 == true);
assert((bool)i2 == true);
assert(!!i0 == false);
assert(!!i1 == true);
assert(!!i2 == true);
}
Non une copie de Puis-je supposer (bool) true == (int) 1 pour tout compilateur C++? :
0 valeurs des types de base (1) (2)mapper sur false
.
Les autres valeurs sont mappées sur true
.
Cette convention a été établie en C d'origine, via ses instructions de contrôle de flux; C n'avait pas de type booléen à l'époque.
C'est une erreur courante de supposer qu'en tant que valeurs de retour de fonction, false
indique un échec. Mais en particulier de main
, c’est false
qui indique le succès. J'ai souvent vu cela se tromper, y compris dans le code de démarrage de Windows pour le langage D (lorsque des personnes telles que Walter Bright et Andrei Alexandrescu se trompent, il est juste dang facile de se tromper ), d’où ce heads-up méfiez-vous méfiez-vous.
Il n'est pas nécessaire de transtyper vers bool
pour les types intégrés car cette conversion est implicite. Cependant, Visual C++ (le compilateur C++ de Microsoft) a tendance à émettre un avertissement de performance (!) Pour cela, un pur avertissement. Une distribution ne suffit pas pour la faire taire, mais une conversion par double négation, c'est-à-dire return !!x
, fonctionne bien. On peut lire !!
en tant qu’opérateur "convertir en bool
", un peu comme -->
peut être lu comme "va à". Pour ceux qui sont profondément dans la lisibilité de la notation de l'opérateur. ;-)
1) C++ 14 §4.12/1 “Une valeur nulle, une valeur de pointeur nulle ou une valeur de pointeur de membre nul est convertie en false
; toute autre valeur est convertie en true
. Pour l’initialisation directe (8.5), une valeur de type std::nullptr_t
peut être converti en une valeur de type bool
; la valeur résultante est false
. ”
2) C99 et C11 §6.3.1.2/1 “Quand une valeur scalaire est convertie en _Bool
, le résultat est 0 si la valeur est égale à 0; sinon, le résultat est 1. ”
Ce qui suit cite la norme C11 (version finale).
6.3.1.2: Lorsque toute valeur scalaire est convertie en _Bool, le résultat est 0 si la comparaison est égale à 0; sinon, le résultat est 1.
bool
(mappé par stdbool.h
au nom interne _Bool
pour C) est lui-même un type entier non signé :
... Le type _Bool et les types entiers non signés qui correspondent aux types entiers signés standard sont les types entiers non signés standard.
Selon 6.2.5p2 :
Un objet déclaré en tant que type _Bool est suffisamment grand pour stocker les valeurs 0 et 1.
Autant que je sache, ces définitions sont sémantiquement identiques à C++ - avec la différence mineure des noms intégrés (!). bool
pour C++ et _Bool
pour C.
Notez que C n'utilise pas le terme rvalues comme C++. Cependant, en C, les pointeurs sont scalaires, donc assigner un pointeur à un _Bool
se comporte comme en C++.
Un autre moyen de supprimer les avertissements (au moins dans MS Visual Studio 2019 C++) consiste à utiliser l'opérateur ternaire et à définir la valeur directe sur true ou false:
int i = 3; // Or another value
bool b = (i ? true : false);
Ou pour le rendre plus clair:
int i = 3; // Or another value
bool b = (i == 0 ? false : true);