web-dev-qa-db-fra.com

opérateur booléen ++ et -

Aujourd'hui, en écrivant du code Visual C++, je suis tombé sur quelque chose qui m'a surpris. Il semble que C++ supporte ++ (incrémentation) pour bool, mais pas - (décrémentation). C'est juste une décision aléatoire, ou il y a une raison derrière ça?

Cela compile:

static HMODULE hMod = NULL;
static bool once = false;
if (!once++)
    hMod = LoadLibrary("xxx");

Cela ne signifie pas:

static HMODULE hMod = NULL;
static bool once = true;
if (once--)
    hMod = LoadLibrary("xxx");
100
Suma

Il vient de l'histoire de l'utilisation de valeurs entières comme booléens.

Si x est un int, mais que je l'utilise comme booléen selon if(x)... alors l'incrémentation signifie que quelle que soit sa valeur de vérité avant l'opération, elle aura un vérité-valeur de true après (sauf débordement).

Cependant, il est impossible de prédire le résultat de -- ne connaissant que la valeur de vérité de x, car cela pourrait entraîner false (si la valeur intégrale est 1) ou true (si la valeur intégrale est quelque chose sinon - cela inclut notamment 0 [false] et 2 ou plus [true]).

Donc, comme un raccourci ++ a fonctionné et -- non.

++ est autorisé sur bools pour la compatibilité avec cela, mais son utilisation est déconseillée dans la norme.


Cela suppose que je niquement utilise x comme booléen, ce qui signifie qu'un débordement ne peut pas se produire tant que je n'ai pas fait ++ assez souvent pour provoquer un débordement de lui-même. Même avec char comme type utilisé et CHAR_BITS quelque chose de bas comme 5, c'est 32 fois avant que ça ne marche plus (c'est encore un argument suffisant pour que ce soit une mauvaise pratique, je ne défends pas la pratique, j'explique juste pourquoi ça marche) pour un 32 bits int nous devons bien sûr utiliser ++ 2 ^ 32 fois avant que ce problème ne survienne. Avec -- bien que cela n'aboutisse à false que si j'ai commencé avec une valeur de 1 pour true, ou commencé avec 0 et utilisé ++ précisément une fois auparavant.

C'est différent si nous commençons avec une valeur qui est juste en dessous de 0. En effet, dans un tel cas, nous pourrions vouloir ++ pour aboutir à la valeur false éventuellement comme dans:

int x = -5;
while(++x)
  doSomething(x);

Cependant, cet exemple traite x comme int partout sauf le conditionnel, il est donc équivalent à:

int x = -5;
while(++x != 0)
  doSomething(x);

Ce qui est différent d'utiliser uniquement x comme booléen.

88
Jon Hanna

ANSI ISO IEC 14882 2003 (c ++ 03):

5.2.6-2

L'opérande de postfix - est décrémenté de manière analogue à l'opérateur postfix ++, sauf que l'opérande ne doit pas être de type bool. [Remarque: pour l'augmentation et la diminution du préfixe, voir 5.3.2. ]

Et sans surprise ...

5.3.2-2

L'opérande de préfixe - est modifié en soustrayant 1. L'opérande ne doit pas être de type bool. Les exigences sur l'opérande de prefix - et les propriétés de son résultat sont par ailleurs les mêmes que celles de prefix ++. [Remarque: pour l'incrémentation et la décrémentation du suffixe, voir 5.2.6. ]

De plus, les 5.6.2-1 et 5.3.2-1 mentionnent que ++ pour les bools doit être vrai et l'annexe D-1 dit que ++ sur les bools est déconseillé.

30
Nordic Mainframe

Pour des raisons historiques, cela a été soutenu. Mais notez que ... L'utilisation d'un opérande de type bool avec l'opérateur ++ est déconseillée voir Section 5.3.2 dans la norme C++ (n3092)

5.3.2 Incrémenter et décrémenter [expr.pre.incr]

  • L'opérande de prefix ++ est modifié en ajoutant 1, ou défini sur true s'il est booléen (cette utilisation est déconseillée). L'opérande doit être une valeur l modifiable. Le type de l'opérande doit être un type arithmétique ou un pointeur vers un type d'objet complètement défini. Le résultat est l'opérande mis à jour; c'est une valeur l, et c'est un champ binaire si l'opérande est un champ binaire. Si x n'est pas de type bool, l'expression ++ x est équivalente à x + = 1 [Remarque: voir les discussions sur l'addition (5.7) et les opérateurs d'affectation (5.17) pour plus d'informations sur les conversions. —Fin note]
  • L'opérande de préfixe - est modifié en soustrayant 1. L'opérande ne doit pas être de type bool. Les exigences sur l'opérande de prefix - et les propriétés de son résultat sont par ailleurs les mêmes que celles de prefix ++.
9
Abhay
  • Avec les anciens standards (C++ 98) ce n'est pas une erreur.
  • Avec les nouvelles normes, l'incrémentation d'un booléen est obsolète. (C++ 11)
  • Vous pouvez utiliser l'incrémentation sur un booléen jusqu'à C++ 17.
2
mustafagonul