equal - operator{} c++




Que fait le compilateur ici: int a=b*(c*d*+ e)? (6)

Ceci est juste des mathématiques de base. Par exemple:

5 * -4 = -20

5 * +4 = 5 * 4 = 20 

-5 * -4 = 20

Négatif * Négatif = Positif

Positif * Négatif = Négatif

Positif * Positif = Positif

C'est l'explication la plus simple qui existe.

Le moins (-) et le plus (+) indiquent simplement si le nombre est positif ou négatif.

Cette question a déjà une réponse ici:

J'ai eu un bogue étrange dans mon programme, et après quelques heures de débogage, j'ai trouvé la ligne très stupide suivante:

int a = b * (c * d *  + e)

Si vous ne le voyez pas: entre d et e j'ai écrit * + , où juste un + était prévu.

Pourquoi cela compile-t-il et que signifie-t-il réellement?


Cela compile car le + est interprété comme unaire unaire, qui effectuera les promotions intégrales sur les types intégraux ou d'énumération et le résultat aura le type d'opérande promu.

En supposant que e soit un type d’énumération intégral ou non délimité, les promotions intégrales finissent par être appliquées de toute façon puisque * applique les conversions arithmétiques habituelles à ses opérandes, ce qui aboutit aux promotions intégrales des types intégraux.

Dans le projet de norme C ++ 5.3.1 [expr.unary.op] :

L'opérande de l'opérateur unaire + doit avoir un type arithmétique, une énumération non délimitée ou un pointeur et le résultat correspond à la valeur de l'argument. La promotion intégrale est effectuée sur des opérandes intégraux ou d'énumération. Le type du résultat est le type de l'opérande promu.

Les promotions intégrales sont traitées dans la section 4.5 [conv.prom] et si les variables e sont d'un type autre que bool, char16_t, char32_t, or wchar_t et ont un rang de conversion inférieur à int, elles seront alors couvertes par le paragraphe 1 :

Une valeur d'un type entier autre que bool, char16_t, char32_t ou wchar_t dont le rang de conversion entier (4.13) est inférieur au rang de int peut être converti en une valeur de type int si int peut représenter toutes les valeurs du type source ; sinon, la prvalue source peut être convertie en une valeur de type unsigned int.

Pour un ensemble complet de cas, nous pouvons examiner cppreference .

Unary plus peut également être utile dans certains cas pour résoudre les ambiguïtés. Un exemple intéressant serait celui de Résoudre la surcharge ambiguë du pointeur de fonction et de std :: function pour un lambda utilisant + .

Notez que pour ces réponses, faisant référence à des valeurs unaires - et négatives, cela est trompeur, comme le montre cet exemple:

#include <iostream>

int main()
{
    unsigned  x1 = 1 ;

    std::cout <<  -x1 << std::endl ;
}

qui se traduit par:

4294967295

Regardez-le en direct en utilisant gcc sur wandbox .

Il est intéressant de noter que le unaire plus a été ajouté à C99 pour la symétrie avec le moins unaire, tiré de la justification pour la norme internationale - Langages de programmation — C :

Unary plus a été adopté par le Comité C89 à partir de plusieurs implémentations, pour une symétrie avec unaire unaire.

et je ne peux pas trouver un bon cas où le casting ne serait pas suffisant pour obtenir la même promotion / conversion souhaitée. L'exemple lambda que je cite ci-dessus, utilisant unary plus pour forcer une expression lambda à être convertie en un pointeur de fonction:

foo( +[](){} ); // not ambiguous (calls the function pointer overload)

pourrait être accompli en utilisant un casting explicite:

foo( static_cast<void (*)()>( [](){} ) );

et on pourrait dire que ce code est meilleur puisque l'intention est explicite.

Il convient de noter que le manuel de référence C ++ annoté ( ARM ) comporte les commentaires suivants:

Unary plus est un accident historique et généralement inutile.


L'opérateur + entre d et e sera traité comme un opérateur unaire + qui déterminera uniquement le signe de e. Ainsi, le compilateur verra cette déclaration comme suit:

int a = b*(c*d*e) ;

Le + est interprété comme un opérateur unaire plus. Il retourne simplement la valeur promoted de son opérande.


Pourquoi compile-t-il? Il compile car + est analysé comme un opérateur unaire plus, et non comme un opérateur d'addition. Le compilateur essaie d'analyser autant que possible sans générer d'erreur de syntaxe. Donc ça:

d * + e

Est analysé comme:

  • d (opérande)
  • * (opérateur de multiplication)
  • + (opérateur unaire plus)
    • e (opérande)

Considérant que ceci:

d*++e;

Est analysé comme:

  • d (opérande)
  • * (opérateur de multiplication)
  • ++ (opérateur pré-incrémenté)
    • e (opérande)

De plus, ceci:

d*+++e;

Est analysé comme:

  • d (opérande)
  • * (opérateur de multiplication)
  • ++ (opérateur pré-incrémenté)
    • + (opérateur unaire plus)
      • e (opérande)

Notez qu'il ne crée pas d'erreur de syntaxe mais l'erreur de compilation "LValue requrired".


Unary + renvoie la valeur promue.
Unary - renvoie la négation:

int a = 5;
int b = 6;
unsigned int c = 3;

std::cout << (a * +b); // = 30
std::cout << (a * -b); // = -30
std::cout << (1 * -c); // = 4294967293 (2^32 - 3)




arithmetic-expressions