简体   繁体   中英

Is conversion int -> unsigned long long defined by the standard

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?

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 2 n 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.

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 2 n where n is the number of bits used to represent the unsigned type).

The least unsigned integer congruent to -1 (modulo 2 sizeof(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*2 n + 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 2 n .


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 2 n . 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 eg 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM