Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Casting negative integer to larger unsigned integer

Tags:

c++

casting

size

I've encountered code that performs the following conversion:

static_cast<unsigned long>(-1)

As far as I can tell, the C++ standard defines what happens when converting a signed integer value to an unsigned integral type (see: What happens if I assign a negative value to an unsigned variable?).

The concern I have in the above code is that the source and destination types may be different sizes and whether or not this has an impact on the result. Would the compiler enlarge the source value type before casting? Would it instead cast to an unsigned integer of the same size and then enlarge that? Or perhaps something else?

To clarify with code,

int nInt = -1;
long nLong = -1; // assume sizeof(long) > sizeof(int)

unsigned long res1 = static_cast<unsigned long>(nInt)
unsigned long res2 = static_cast<unsigned long>(nLong);

assert(res1 == res2); // ???

Basically, should I be worrying about writing code like

static_cast<unsigned long>(-1L)

over

static_cast<unsigned long>(-1)
like image 708
Thomas Eding Avatar asked Feb 14 '14 01:02

Thomas Eding


2 Answers

From the C++11 standard, 4.7 "Integral conversions", para 2:

If the destination type is unsigned, the resulting value is the least unsigned integer congruent to the source integer (modulo 2n where n is the number of bits used to represent the unsigned type).

In other words, when converting to an unsigned integer, only the value of the input matters, not its type. Converting -1 to an n-bit unsigned integer will always give you 2n-1, regardless of which integer type the -1 started as.

like image 88
Ross Smith Avatar answered Oct 19 '22 19:10

Ross Smith


This is a good question and the draft C++ standard on this section 4.7 Integral conversions which says:

If the destination type is unsigned, the resulting value is the least unsigned integer congruent to the source integer (modulo 2n where n is the number of bits used to represent the unsigned type).[...]

is not the most straight forward to interpret, in this case I would go back to the draft C99 standard which says:

Otherwise, if the new type is unsigned, the value is converted by repeatedly adding or subtracting one more than the maximum value that can be represented in the new type until the value is in the range of the new type.49

where footnote 49 helpfully says:

The rules describe arithmetic on the mathematical value, not the value of a given type of expression.

This is more straight forward and clearly gives us the result as -1 + MAX + 1 which is MAX, regardless of what type of the operand is.

like image 23
Shafik Yaghmour Avatar answered Oct 19 '22 17:10

Shafik Yaghmour