web-dev-qa-db-fra.com

Casting int pour bool en C / C ++

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++? :

  1. Coulée en sens inverse (int -> bool).
  2. Pas de discussion là-bas des valeurs non nulles et non égales.
26
cp.engr

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

34

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

12

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);
0
Michel Keijzers