警告:此十进制常量仅在ISO C90中无符号

时间:2012-03-30 10:29:16

标签: c compiler-construction long-integer iso c89

一段代码:

long rangeVar = 0;
rangeVar = atol(p_value);

if (rangeVar >= -2147483648 && rangeVar <= 2147483647)

编译时我得到:

  

警告:此十进制常量仅在ISO C90

中无符号

先谢谢

3 个答案:

答案 0 :(得分:13)

十进制整数常量类型的规则在ISO C标准的1990年和1999年版本之间发生了变化。

在1990版本中,未加十进制的十进制整数常量类型是可以表示其值的intlong intunsigned long int中的第一个。 (C90没有long longunsigned long long类型。

在1999和2011版本中,其类型是intlong intlong long int之一;它永远不会是任何未签名的类型。

特定常量的类型(例如2147483648)将根据您正在使用的编译器的整数类型的范围而变化。如果编译器的long类型恰好是32位,那么如果编译器使用C90规则,则2147483648将为unsigned long类型,如果使用C11规则,则long long类型为long long类型(int保证至少为64位)。编译器正在警告你。

您可以添加后缀以指定常量的类型 - 但是对于普通签名的U没有后缀。您可以为unsigned int添加L,为long添加UL,为无符号长添加-2147483648,依此类推。

重要的是要记住,2147483648 不是整数常量;而-2147483648本身是一个整数常量,而unsigned long是一个将一元减号运算符应用于该常量的表达式。在C90规则下,如果常量的类型为2147483648,那么这是无符号一元减号,在无符号算术规则下产生值2147483648。根据C99或C11规则,long long可能是(带签名的)-2147483648类型,否定它会产生long long,同样类型为(-2147483647 - 1)

您有时会看到使用int的代码来避免此问题;给定32位2147483647int的类型为int,表达式的结果会产生预期的{{1}}值而不会溢出。

当然,如果您的编译器对整数类型有不同的大小,这可能会变得更加复杂。

答案 1 :(得分:10)

是的,这是编译器无法很好地处理的一件事。问题是在编译期间,这是否定的数字2147483648,并且2147483648超出整数的范围。即使-2147483648也不会!

无论如何,要删除警告,您可以通过编写-2147483648LL将常量转换为64位数。
但这有点过头了,所以首选的方法是使用INT_MIN作为常数。但是,您需要包含<limits.h>

答案 2 :(得分:1)

是的,2147483648不是一个有效的正值,因为它在32位机器上超出了2的补码范围,所以他们只是试图警告你,在某些编译器上,这可能不会给你你想要的价值以现代方式处理否定。

我觉得值得添加另一个答案,指出如果你看看大多数limits.h实现,你会看到他们使用(-2147483647 - 1)来解决这个问题。