Question

I can't find the exact specification of how int value is converted to unsigned long long in the standard. Various similar conversions, such as int -> unsigned, unsigned -> int (UB if negative), unsigned long long -> int, etc. are specified

For example GCC, -1 is converted to 0xffffffffffffffff, not to 0x00000000ffffffff. Can I rely on this behavior?

Was it helpful?

Solution

Yes, this is well defined, it is basically adding max unsigned long long + 1 to -1 which will always be max unsigned long long. This is covered in the draft C++ standard 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). [ Note: In a two’s complement representation, this conversion is conceptual and there is no change in the bit pattern (if there is no truncation). —end note ]

it does the same thing as C99 but the draft C99 standard is easier to understand, from section 6.3.1.3 Signed and unsigned integers:

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 says:

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

OTHER TIPS

Yes, it's defined:

C++11 § 4.7 [conv.integral]/2 says this:

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).

The least unsigned integer congruent to -1 (modulo 2sizeof(unsigned long long)) is the largest value of unsigned long long possible.

Unsigned integers have guaranteed modulo arithmetic. Thus any int value v is converted to the unsigned long value u such that u = K*2n+v, where K is either 0 or 1, and where n is the number of value representation bits for unsigned long. In other words, if v is negative, just add 2n.


The power of 2 follows from the C++ standard's requirement that integers be represented with a pure binary system. With n value representation bits the number of possible values is 2n. There is not such a requirement for floating point types (you can use std::numeric_limits to check the radix of the representation of floating point values).


Also note that in order to cater to some now archaic platforms, as well as one popular compiler that does things its own way, the standard leaves the opposite conversion as undefined behavior when the unsigned value is not directly representable as a signed value. In practice, on modern systems all compilers can be told to make that reverse conversion the exact opposite of the conversion to unsigned type, and e.g. Visual C++ does that by default. However, it's worth keeping in mind that there's no formal support, so that portable code incurs a slight (now with modern computers needless) inefficiency.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top