警告:此十进制常量仅在ISO C90中无符号
一段代码:
long rangeVar = 0; rangeVar = atol(p_value); if (rangeVar >= -2147483648 && rangeVar <= 2147483647)
在编译时,我得到:
警告:此十进制常量仅在ISO C90中无符号
提前致谢
十进制整数常量类型的规则在ISO C标准的1990年和1999年版本之间改变。
在1990版本中,未加十进制的十进制整数常量类型是int
, long int
或unsigned long int
中的第一个,其中可以表示其值。 (C90没有long long
或unsigned long long
型)。
在1999和2011版本中,它的类型是int
, long int
, long long int
; 它永远不会是任何无符号类型。
特定常量的类型(例如2147483648
)将根据您正在使用的编译器的整数类型的范围而变化。 如果编译器的long
类型恰好是32位,那么如果编译器使用C90规则,则2147483648
将为unsigned long
类型;如果使用C11规则,则为long long
类型( long long
保证至少为64位)。 编译器正在警告你这件事。
您可以添加后缀以指定常量的类型 – 但是对于普通的signed int
没有后缀。 您可以为unsigned int
添加U
,为long
L
,为unsigned int
添加UL
,依此类推。
重要的是要记住-2147483648
不是整数常量; 而2147483648
本身是一个整型常量,而-2147483648
是一个将一元减号运算符应用于该常量的表达式。 根据C90规则,如果常量是unsigned long
类型,那么这是一个无符号一元减号,它在无符号算术规则下产生值2147483648
。 根据C99或C11规则, 2147483648
可能是long long
)类型(签名),否则它产生-2147483648
,也是long long
类型。
您有时会看到使用(-2147483647 - 1)
代码来避免此问题; 给定32位int
, 2147483647
是int
类型,表达式的结果产生没有溢出的预期int
值。
当然,如果您的编译器对整数类型有不同的大小,这可能会变得更加复杂。
是的,这是编译器无法很好地处理的一件事。 问题是在编译期间,这是否定的数字2147483648,并且2147483648超出整数的范围。 即使-2147483648不会!
无论如何,要消除警告,您可以通过写-2147483648LL
将常量变为64位数。
但这INT_MIN
过分,所以首选的方法是使用INT_MIN
作为常量。 但是你需要包含
。
是的,2147483648不是一个有效的正值,因为它在32位机器上超出了2的补码范围,所以他们只是试图警告你,在某些编译器上,如果它们不处理,这可能不会给你你想要的值以现代方式否定。
我觉得值得添加另一个答案,指出如果你看看大多数limits.h实现,你会发现他们使用(-2147483647 - 1)
来解决这个问题。