2012-03-30 25 views
15

一段代码:警告:这个小数常量是无符号只在ISO C90

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

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

在编译我得到:

警告:这个小数常量仅ISO C90

是无符号

在此先感谢

+1

C90没有'long long'类型,这就是它处理这些数字与C99不同的原因。 – Lindydancer 2012-03-30 11:02:31

+2

供参考:正确的答案在这里找到: http://stackoverflow.com/questions/2347936/cant-get-rid-of-this-decimal-constant-is-unsigned-only-in-iso-c90-警告 – natersoz 2013-07-01 15:58:19

回答

9

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

无论如何,为了摆脱这个警告,你可以通过编写-2147483648LL来将常量变成64位数。
虽然这是过度的,所以最好的方法是使用INT_MIN作为常量。但是你需要包含<limits.h>

+2

不完全正确/准确。 C89表示:“整数常量的类型是其中可以表示其值的对应列表中的第一个。非混用十进制:int,long int,unsigned long int;未定义的八进制或十六进制:......。因此,对于以某种兼容模式工作的旧编译器或现代编译器2147483648,如果它无法放入'unsigned long',而不是'int',则会失败。 C99用'long long int'和'unsigned long long int'扩展这个列表,而在C99模式下,后缀(U)LL是不必要的。当然,编译器bug也不是前所未闻的。 – 2012-03-30 11:41:55

+0

那么你会如何解释警告?我测试过了,并且我得到了与使用gcc 4.3.2的OP相同的警告,并且在使用LL后缀时没有发出警告。 – 2012-03-30 11:47:33

+0

这意味着默认情况下,gcc不处于C99模式。如果你添加了-std = c99,它会产生一个不同的警告:“由于数据类型范围有限,比较总是成立的”。惊喜。我甚至不确定它默认的模式以及原因。 – 2012-03-30 12:00:12

1

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

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

+0

awsome trick! – malat 2014-03-02 10:24:18

12

十进制整数常量类型的规则在ISO C标准的1990版和1999版之间有所变化。

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

在1999和2011版本中,其类型为intlong intlong long int之一;它从来没有任何无符号类型。

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

您可以添加后缀来指定常量的类型 - 但没有纯后缀int的后缀。对于unsigned int,L,对于long,UL可以添加U,对于无符号长等等。

请务必记住-2147483648而不是整数常量;而是2147483648本身是一个整数常量,而-2147483648是一个表达式,它将一个一元减运算符应用于该常量。根据C90规则,如果常量的类型为unsigned long,那么这是一个无符号的一元减号,它在无符号算术的规则下产生值2147483648。根据C99或C11规则,2147483648很可能是(有符号)long long类型,并且否定它产生-2147483648,也是类型long long

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

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

+0

谢谢你提供了非常明确的答案。为了完整起见,可能值得补充的是关于实现定义的_extended整数类型_的1999版C标准。如果没有一种类型是足够的,那么常量可以具有最终类型的扩展类型。例如,在GCC(版本4.4.7)中,常量“9223372036854775808”(即2^63)被“提升”为16字节数据类型“__int128_t”(尽管它不是“真”EIT)。另外请注意,这些规则对于八进制和十六进制表示稍有不同,但我猜测OP只对十进制有兴趣。 – 2014-06-01 23:21:57

+1

“U”后缀表示无符号,但不一定是“unsigned int”,例如,如果只有'U'的十进制常量对于'unsigned int'来说太大,它将具有'unsigned long'类型。同样,如果该值不符合“长”,则“L”将“升级”为“long long”。 – 2017-01-10 01:35:27

相关问题