What does the compiler do here: int a = b * (c * d * + e)? [duplicate]

I had a strange bug in my program, and after a few hours of debugging, I found the following very stupid line:

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

If you don't see it: Between d and e I wrote * +, where just a +was intended.

Why does this compile and what does it actually mean?


The + is interpreted as an unary plus operator. It simply returns the promoted value of its operand.


Unary + returns the promoted value.
Unary - returns the negation:

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)

This compiles because the + is being interpreted as unary plus, which will perform the integral promotions on integral or enumeration types and the result will have the type of the promoted operand.

Assuming e is an integral or unscoped enumeration type would end up having the integral promotions applied anyway since * applies the usual arithmetic conversions to its operands which ends up at the integral promotions for integral types.

From the draft C++ standard 5.3.1 [expr.unary.op]:

The operand of the unary + operator shall have arithmetic, unscoped enumeration, or pointer type and the result is the value of the argument. Integral promotion is performed on integral or enumeration operands. The type of the result is the type of the promoted operand.

The integral promotions are covered in section 4.5 [conv.prom] and if the variables e is a type other than bool, char16_t, char32_t, or wchar_t and have conversion rank less than int then it would be covered by paragraph 1:

A prvalue of an integer type other than bool, char16_t, char32_t, or wchar_t whose integer conversion rank (4.13) is less than the rank of int can be converted to a prvalue of type int if int can represent all the values of the source type; otherwise, the source prvalue can be converted to a prvalue of type unsigned int.

For a complete set of cases we can look at cppreference.

Unary plus can also be useful in some cases to resolve ambiguity, an interesting case would be from Resolving ambiguous overload on function pointer and std::function for a lambda using +.

Note, for those answers, referring to unary - and negative values, this is misleading, as this example shows:

#include <iostream>

int main()
{
    unsigned  x1 = 1 ;

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

which results in:

4294967295

See it live using gcc on wandbox.

It is interesting to note that unary plus was added to C99 for symmetry with unary minus, from the Rationale for International Standard—Programming Languages—C:

Unary plus was adopted by the C89 Committee from several implementations, for symmetry with unary minus.

and I can not come up with a good case where casting would not be sufficient to achieve the same desired promotion/conversion. The lambda example I cite above, using unary plus to force a lambda expression to be converted to a function pointer:

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

could be accomplished using a explicit cast:

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

and it could be argued this code is better since the intention is explicit.

Worth noting that Annotated C++ Reference Manual(ARM) it has the following commentary:

Unary plus is a historical accident and generally useless.


As what they have explained, (+) and (-) were just used as unary operator:

Unary operators act on only one operand in an expression

int value = 6;
int negativeInt = -5;
int positiveInt = +5;

cout << (value * negativeInt); // 6 * -5 = -30
cout << (value * positiveInt); // 6 * +5 = 30

cout << (value * - negativeInt); // 6 * -(-5) = 30
cout << (value * + negativeInt); // 6 * +(-5) = -30

cout << (value * - positiveInt); // 6 * -(+5) = -30
cout << (value * + positiveInt); // 6 * +(+5) = 30

so from your code:

int b = 2;
int c = 3;
int d = 4;
int e = 5;

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

//result: 2 * (3 * 4 * (+5) ) = 120