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

一段代码:

long rangeVar = 0; rangeVar = atol(p_value); if (rangeVar >= -2147483648 && rangeVar <= 2147483647) 

在编译时,我得到:

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

提前致谢

十进制整数常量类型的规则在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保证至少为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位int2147483647int类型,表达式的结果产生没有溢出的预期int值。

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

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

无论如何,要消除警告,您可以通过写-2147483648LL将常量变为64位数。
但这INT_MIN过分,所以首选的方法是使用INT_MIN作为常量。 但是你需要包含

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

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