开发者

How portable is casting -1 to an unsigned type?

The other day, I came across this construct:

static_cast<size_type>(-1)

in some example C++ code, which is likely (depending on the details of where size_type is from) to be equivalent to the following C:

(size_t)(-1)

As I understand it, it works based on the fact that the representation of -1 in twos complement arithmetic is 11111...1, for as many bits as you have, so this is a quick wa开发者_运维知识库y of getting the maximum value that an unsigned type like size_t can hold. However, my understanding is also that C doesn't guarantee that twos complement will be used; if the C implementation uses one's complement, this will be 1 less than the the maximum value, and if it's using signed magnitude, it will be just over half the maximum value.

Is there some wrinkle that I'm missing that insures that this works right regardless of the representation of signed integers being used? Does it differ between C and C++ (many surprising things do)?


The requirements on unsigned arithmetic guarantee that casting -1 to an unsigned type will produce the largest number possible for the target type. C99, §6.2.5/9: "...a result that cannot be represented by the resulting unsigned integer type is reduced modulo the number that is one greater than the largest value that can be represented by the resulting type."

This is the same in C and C++ (in the C++ standard, similar wording is found in footnote 41 -- it's not normative, but it's explaining other wording that is).


To be on a "safe" side and do it "right" (C++) way, worth looking at STL:

std::numeric_limits<size_t>::max()


"As I understand it, it works based on the fact that the representation of -1 in twos complement arithmetic is...".

No, it is not based on that fact at all. It is based on the standard requirement, that singed values converted to N-bit unsigned type have to produce an unsigned value, which is "equal" to the original signed one modulo 2^N.

It has to work that way regardless of the signed representation used by the implementation. In case of 2's complement it works that way by itself, but for other representations the compiler will have to do the extra work in order to satisfy the standard requirement.


If you're looking to get the maximum (or minimum) value of a certain type in a portable way, it is best to use the standard numeric_limits class as follows.

#include <limits>

size_type max = std::numeric_limits<size_type>::max()
size_type min = std::numeric_limits<size_type>::min()

I suspect that some implementations of these functions may use the cast you describe as the platform-optimal way to get at the min/max.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜