开发者

Testing for a maximum unsigned value

开发者 https://www.devze.com 2023-02-01 02:49 出处:网络
Is this the correct way to test for a maximum unsigned value in C and C++ code: if(foo == -1) { // at max possible value

Is this the correct way to test for a maximum unsigned value in C and C++ code:

if(foo == -1)
{
    // at max possible value
}

where foo is an unsigned in开发者_JAVA技巧t, an unsigned short, and so on.


For C++, I believe you should preferably use the numeric_limits template from the <limits> header :

if (foo == std::numeric_limits<unsigned int>::max())
    /* ... */

For C, others have already pointed out the <limits.h> header and UINT_MAX.


Apparently, "solutions which are allowed to name the type are easy", so you can have :

template<class T>
inline bool is_max_value(const T t)
{
    return t == std::numeric_limits<T>::max();
}

[...]

if (is_max_value(foo))
    /* ... */


I suppose that you ask this question since at a certain point you don't know the concrete type of your variable foo, otherwise you naturally would use UINT_MAX etc.

For C your approach is the right one only for types with a conversion rank of int or higher. This is because before being compared an unsigned short value, e.g, is first converted to int, if all values fit, or to unsigned int otherwise. So then your value foo would be compared either to -1 or to UINT_MAX, not what you expect.

I don't see an easy way of implementing the test that you want in C, since basically using foo in any type of expression would promote it to int.

With gcc's typeof extension this is easily possible. You'd just have to do something like

if (foo == (typeof(foo))-1)


As already noted, you should probably use if (foo == std::numeric_limits<unsigned int>::max()) to get the value.

However for completeness, in C++ -1 is "probably" guaranteed to be the max unsigned value when converted to unsigned (this wouldn't be the case if there were unused bit patterns at the upper end of the unsigned value range).

See 4.7/2:

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

Note that specifically for the unsigned int case, due to the rules in 5/9 it appears that if either operand is unsigned, the other will be converted to unsigned automatically so you don't even need to cast the -1 (if I'm reading the standard correctly). In the case of unsigned short you'll need a direct check or explicit cast because of the automatic integral promotion induced by the ==.


using #include <limits.h> you could just do

if(foo == UINT_MAX)

if foo is an unsigned int it has valued [0 - +4,294,967,295] (if 32 bit)

More : http://en.wikipedia.org/wiki/Limits.h

edit: in C

if you do

#include <limits.h>
#include <stdio.h>

int main() {
    unsigned int x = -1;
    printf("%u",x);
    return 0;
}

you will get the result 4294967295 (in a 32-bit system) and that is because internally, -1 is represented by 11111111111111111111111111111111 in two's complement. But because it is an unsigned, there is now no "sign bit" therefore making it work in the range [0-2^n]

Also see : http://en.wikipedia.org/wiki/Two%27s_complement

See other's answers for the C++ part std::numeric_limits<unsigned int>::max()


I would define a constant that would hold the maximum value as needed by the design of your code. Using "-1" is confusing. Imagine that someone in the future will change the type from unsigned int to int, it will mess your code.


Here's an attempt at doing this in C. It depends on the implementation not having padding bits:

#define IS_MAX_UNSIGNED(x) ( (sizeof(x)>=sizeof(int)) ? ((x)==-1) : \
                             ((x)==(1<<CHAR_BIT*sizeof(x))-1) )

Or, if you can modify the variable, just do something like:

if (!(x++,x--)) { /* x is at max possible value */ }

Edit: And if you don't care about possible implementation-defined extended integer types:

#define IS_MAX_UNSIGNED(x) ( (sizeof(x)>=sizeof(int)) ? ((x)==-1) : \
                             (sizeof(x)==sizeof(short)) ? ((x)==USHRT_MAX) : \
                             (sizeof(x)==1 ? ((x)==UCHAR_MAX) : 42 )

You could use sizeof(char) in the last line, of course, but I consider it a code smell and would typically catch it grepping for code smells, so I just wrote 1. Of course you could also just remove the last conditional entirely.

0

精彩评论

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

关注公众号