Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Compiler warning for unary operation on unsigned int

I have this sample code which generates the following warning (VS2008 compiler with SP1):

warning C4146: unary minus operator applied to unsigned type, result still unsigned

Code:

void f(int n)
{
}

int main()
{
    unsigned int n1 = 9;
    f(-n1);
}

But since function f is taking it's parameter as an int shouldn't this code compile without any warnings?

like image 927
Naveen Avatar asked Nov 24 '10 13:11

Naveen


2 Answers

if x is of type unsigned int, then so is -x and it is virtually equivalent to 2n-x (where n is most likely 32). To avoid the warning and get correct behavior, cast to int:

f(-static_cast<int>(n));

I would recommend reading the "Expressions" chapter of the C++ standard. There you'll see that in the expression -x integral promotions take place on x, which means that almost anything gets promoted to int, but unsigned int is not.

Look at this very interesting example:

template<class T>
void f(T x)
{
  //somehow print type info about x, e.g. cout << typeid(x).name() or something
}

int main()
{
  char x;
  f(x);
  f(+x);
  f(-x);
}

prints:

char
int 
int

But char -> int is an integral promotion, whereas unsigned int -> int is a conversion

like image 190
Armen Tsirunyan Avatar answered Nov 15 '22 07:11

Armen Tsirunyan


Standard 5.3.1/7

The operand of the unary - operator shall have arithmetic or enumeration type and the result is the negation of its operand. Integral promotion is performed on integral or enumeration operands. The negative of an unsigned quantity is computed by subtracting its value from 2n, where n is the number of bits in the promoted operand. The type of the result is the type of the promoted operand.

And the paragraph on Integral Promotion 4.5/1

An rvalue of type char, signed char, unsigned char, short int, or unsigned short int can be converted to an rvalue of type int if int can represent all the values of the source type; otherwise, the source rvalue can be converted to an rvalue of type unsigned int.

i.e. an unsigned int will not be promoted to an int.

like image 21
Andreas Brinck Avatar answered Nov 15 '22 08:11

Andreas Brinck