web-dev-qa-db-fra.com

Le type booléen C / C ++ est-il toujours garanti d'être 0 ou 1 lorsqu'il est transtypé en int?

De nombreux compilateurs semblent ne conserver que 0 ou 1 dans les valeurs booléennes, mais je ne suis pas sûr que cela fonctionnera toujours:

int a = 2;
bool b = a;
int c = 3 + b; // 4 or 5?
43
mojuba

Oui:

En C++ (§4.5/4):

Une rvalue de type bool peut être convertie en une rvalue de type int, false devenant nul et true devenant un.

En C, lorsqu'une valeur est convertie en _Bool, il devient 0 ou 1 (§6.3.1.2/1):

Lorsqu'une valeur scalaire est convertie en _Bool, le résultat est 0 si la valeur se compare à 0; sinon, le résultat est 1.

Lors de la conversion en int, c'est assez simple. int peut contenir 0 et 1, il n'y a donc pas de changement de valeur (§6.3.1.3).

47
Matthew Flaschen

Eh bien, pas toujours ...

const int n = 100;
bool b[n];
for (int i = 0; i < n; ++i)
{
    int x = b[i];
    if (x & ~1)
    {
        std::cout << x << ' ';
    }
}

Sortie sur mon système:

28 255 34 148 92 192 119 46 165 192 119 232 26 195 119 44 255 34 96 157 192 119
8 47 78 192 119 41 78 192 119 8 250 64 2 194 205 146 124 192 73 64 4 255 34 56 2
55 34 224 255 34 148 92 192 119 80 40 190 119 255 255 255 255 41 78 192 119 66 7
8 192 119 192 73 64 240 255 34 25 74 64 192 73 64

La raison de cette sortie apparemment bizarre est expliquée dans la norme 3.9.1 §6:

Les valeurs de type bool sont soit true ou false. L'utilisation d'une valeur bool de la manière décrite par la présente Norme internationale comme "non définie", par exemple par l'examen de la valeur d'un objet automatique non initialisé, peut entraîner son comportement comme s'il n'était ni true ni false.

19
fredoverflow

Est-ce C/C++ .......

Il n'y a pas de langage nommé C/C++.

type booléen toujours garanti à 0 ou 1 lors de la transtypage en int?

En C++ oui car la section $ 4.5/4 dit

Une rvalue de type bool peut être convertie en une rvalue de type int, false devenant nul et true devenant un.

.

int c = 3 + b; // 4 ou 5?

La valeur de c sera 4

18
Prasoon Saurav

Un autre exemple lorsque vous êtes hors du bateau sûr:

  bool b = false;
  *(reinterpret_cast<char*>(&b)) = 0xFF;
  int from_bool = b;
  cout << from_bool << " is " << (b ? "true" : "false");

Sortie (g ++ (GCC) 4.4.7):

  255 is true

A ajouter au exemple de FredOverflow .

8
Alex Che

Il n'y a pas de type booléen en C pré C99 (comme C90), mais le type booléen en C99/C++ est toujours garanti à 0 ou 1.

En C, toutes les opérations booléennes sont garanties de retourner 0 ou 1, que le type booléen soit défini ou non.

Donc a && b ou !a ou a || b renverra toujours 0 ou 1 en C ou C++ quel que soit le type de a et b.

3
hhafez

Les types avec des bits de remplissage peuvent se comporter étrangement si les bits de remplissage ne contiennent pas les valeurs attendues pour le type. La plupart des implémentations C89 n'utilisaient pas de bits de remplissage avec aucun de leurs types entiers, mais C99 exige que les implémentations définissent un tel type: _Bool. Lire un _Bool lorsque tous ses bits sont nuls donnera zéro. Écriture d'une valeur non nulle dans un _Bool mettra ses bits à un modèle qui donnera 1 lors de la lecture. L'écriture de zéro mettra les bits à un modèle (qui peut ou non être tout à zéro) qui donnera 0 lors de la lecture.

Sauf indication contraire dans la documentation d'une implémentation, tout modèle de bits autre que tous les bits zéro qui n'aurait pas pu être produit en stockant une valeur nulle ou non nulle dans un _Bool est une représentation piège; la Norme ne dit rien de ce qui se passera si l'on tente de lire une telle valeur. Étant donné, par exemple.

union boolChar { _Bool b; unsigned char c; } bc;

stockage de zéro dans bc.c et lecture bc.b donnera zéro. Stocker zéro ou un dans bc.b définira bc.c aux valeurs qui, si elles sont écrites, entraîneront bc.b pour maintenir zéro ou un. Stockage de toute autre valeur dans bc.c et lecture bc.b produira un comportement indéfini.

1
supercat