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

use*_*514 20 c compiler-construction iso c89 long-integer

一段代码:

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

if (rangeVar >= -2147483648 && rangeVar <= 2147483647)
Run Code Online (Sandbox Code Playgroud)

在编译时,我得到:

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

提前致谢

Kei*_*son 15

十进制整数常量类型的规则在ISO C标准的1990和1999版本之间改变.

在1990年版,一个无后缀十进制整数常量的类型是第一的int,long intunsigned long int在其值可以被表示.(C90没有long longunsigned long long类型).

在1999年和2011年的版本,它的类型是一int,long int,long long int,它永远不会是任何未签名的类型.

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

您可以添加后缀以指定常量的类型 - 但是没有后缀用于普通签名int.您可以添加Ufor unsigned int,Lfor long,ULfor unsigned long等等.

重要的是要记住,重要的-2147483648不是一个整型常量; 相反2147483648,它本身是一个整型常量,-2147483648是一个将一元减运算符应用于该常量的表达式.根据C90规则,如果常量是类型unsigned long,那么这是一个无符号一元减号,它在无符号算术的规则下产生该值2147483648.根据C99或C11规则,2147483648可能是类型(签名)long long,并且否定它的收益-2147483648,也是类型long long.

您有时会看到(-2147483647 - 1)用于避免此问题的代码; 给定的32位int,2147483647是类型int和表达的结果产生的预期int值,而不溢出.

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


Mr *_*ter 10

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

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

  • 不完全正确/准确.C89说:`整数常量的类型是相应列表中可以表示其值的第一个.unsuffixed decimal:int,long int,unsigned long int; 未填充的八进制或十六进制:...`.因此,对于在某种兼容模式下工作的旧编译器或现代编译器,如果它不能适应`unsigned long`而不是普通的`int`,则会失败.C99使用`long long int`和`unsigned long long int`扩展该列表,在C99模式下,后缀(U)LL是不必要的.当然,编译器错误也不是闻所未闻的. (2认同)