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

von4xj4u  于 2023-01-04  发布在  其他
关注(0)|答案(3)|浏览(314)

代码段:

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

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

编译时,我得到:
警告:此十进制常量仅在ISO C90中无符号
提前致谢

bn31dyow

bn31dyow1#

十进制整数常量类型的规则在ISO C标准的1990和1999版本之间发生了变化。
在1990年的版本中,无后缀十进制整型常量的类型是intlong intunsigned long int中的第一个,它的值可以用这些类型表示(C90没有long longunsigned long long类型)。
在1999和2011版本中,其类型为intlong intlong long int中的一种;它从来都不是无符号类型。
特定常量的类型(例如2147483648)将根据您使用的编译器的整数类型范围而变化。如果您的编译器的long类型恰好是32位,那么2147483648将是unsigned long类型(如果您的编译器使用C90规则),如果使用C11规则,则为long long类型(long long保证至少为64位)。编译器会就此发出警告。
你可以添加后缀来指定常量的类型--但是对于纯符号的int没有后缀,你可以为unsigned int添加U,为long添加L,为无符号的long添加UL,等等。
记住-2147483648 * 不是 * 整型常量是很重要的;而2147483648本身是整型常量,并且-2147483648是将一元减运算符应用于该常量的表达式。在C90规则下,如果常量是unsigned long类型,则这是 unsigned 一元减,其在无符号算术规则下产生值2147483648。在C99或C11规则下,2147483648很可能是类型(有符号)long long,并且对其求反产生-2147483648,其也是类型long long
您有时会看到使用(-2147483647 - 1)来避免此问题的代码;给定32位X1 M30 N1 X,X1 M31 N1 X是类型X1 M32 N1 X,并且表达式的结果产生预期的X1 M33 N1 X值而没有溢出。
当然,如果您的编译器对整数类型有不同的大小,这可能会变得更加复杂。
更新:当我写这篇文章的时候,gcc的默认方言是-std=gnu89,从那以后,它被改成了-std=gnu11(或者在未发布的版本中是-std=gnu17),我不确定这对警告有什么影响。

ojsjcaue

ojsjcaue2#

是的,这是编译器没有很好处理的一件事。问题是在编译过程中,这是一个被取反的数字2147483648,2147483648超出了整数的范围。即使-2147483648也不会!
无论如何,要消除警告,可以通过写入-2147483648LL将常量转换为64位数。
不过这有点过分了,所以首选的方法是使用INT_MIN作为常量,但是这样就需要包含<limits.h>

pgky5nke

pgky5nke3#

是的,2147483648不是一个有效的正值,因为它超出了32位机器上2的补码的范围,所以他们只是想警告你,在一些编译器上,如果他们不以现代的方式处理求反,这可能不会给予你想要的值。
我觉得有必要补充另一个答案,指出如果您查看大多数limits. h实现,您会发现它们使用(-2147483647 - 1)解决了这个问题。

相关问题