测试最大无符号值
这是在C和C ++代码中测试最大无符号值的正确方法:
if(foo == -1) { // at max possible value }
其中foo是unsigned int
, unsigned short
,依此类推。
对于C ++,我相信您最好使用
标头中的numeric_limits
模板:
if (foo == std::numeric_limits::max()) /* ... */
对于C,其他人已经指出了
头和UINT_MAX
。
显然,“允许命名类型的解决方案很容易”,因此您可以:
template inline bool is_max_value(const T t) { return t == std::numeric_limits::max(); } [...] if (is_max_value(foo)) /* ... */
我想你问这个问题,因为在某个时刻你不知道变量foo
的具体类型,否则你自然会使用UINT_MAX
等。
对于C,您的方法仅适用于转换等级为int
或更高的类型。 这是因为在比较unsigned short
值之前,例如,如果所有值都适合,则首先转换为int
,否则转换为unsigned int
。 那么你的价值foo
将被比作-1
或UINT_MAX
,而不是你所期望的。
我没有看到在C中实现您想要的测试的简单方法,因为在任何类型的表达式中基本上使用foo
会将其提升为int
。
使用gcc的扩展类型,这很容易实现。 你只需要做类似的事情
if (foo == (typeof(foo))-1)
如前所述,您应该使用if (foo == std::numeric_limits
来获取值。
但是为了完整性,在C ++中, -1
“可能”保证在转换为无符号时是最大无符号值(如果在无符号值范围的上端存在未使用的位模式,则不会出现这种情况)。
见4.7 / 2:
如果目标类型是无符号的,则结果值是与源整数一致的最小无符号整数(模2 ^ n,其中n是用于表示无符号类型的位数)。 [注意:在二进制补码表示中,此转换是概念性的,并且位模式没有变化(如果没有截断)。 ]
请注意,特别是对于unsigned int
情况,由于5/9中的规则,如果任一操作数是无符号的,另一个将自动转换为无符号,因此您甚至不需要转换-1
(如果我’正确阅读标准)。 在unsigned short的情况下,由于==
引起的自动积分提升,您需要直接检查或显式转换。
使用#include
你可以做到
if(foo == UINT_MAX)
如果foo是unsigned int
它的值为[0 – +4,294,967,295](如果是32位)
更多: http : //en.wikipedia.org/wiki/Limits.h
编辑:在C
如果你这样做
#include #include int main() { unsigned int x = -1; printf("%u",x); return 0; }
你将得到结果4294967295
(在一个32位系统中),这是因为在内部,-1由二进制补码中的11111111111111111111111111111111
表示。 但因为它是unsigned
,所以现在没有“符号位”因此使其在[0-2 ^ n]范围内工作
另见: http : //en.wikipedia.org/wiki/Two%27s_complement
请参阅其他C++
部分的答案std::numeric_limits
我将定义一个常量,它将根据代码设计的需要保持最大值。 使用“-1”令人困惑。 想象一下,将来有人会将类型从unsigned int更改为int,这会弄乱你的代码。
这是尝试在C中执行此操作。这取决于没有填充位的实现:
#define IS_MAX_UNSIGNED(x) ( (sizeof(x)>=sizeof(int)) ? ((x)==-1) : \ ((x)==(1<
或者,如果您可以修改变量,只需执行以下操作:
if (!(x++,x--)) { /* x is at max possible value */ }
编辑:如果您不关心可能的实现定义的扩展整数类型:
#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 )
当然,你可以在最后一行使用sizeof(char)
,但我认为这是一种代码气味,并且通常会抓住代码气味,所以我只写了1.当然你也可以完全删除最后一个条件。