#include <limits.h>
#include <stdio.h>
int main() {
long ival = 0;
printf("ival: %li, min: %i, max: %i, too big: %i, too small: %i\n",
ival, INT_MIN, INT_MAX, ival > INT_MAX, ival < INT_MIN);
}
这给出了输出:
ival: 0, min: -2147483648, max: 2147483647, too big: 0, too small: 1
这怎么可能?
(我实际上遇到了getargs.c
convertsimple
中CPython 2.7.3中的这个问题/错误。如果您在case 'i'
中查找代码,则会检查{ {1}}这对我来说总是如此。另见test case source with further references。)
好吧,我现在测试了几个不同的编译器。为x86编译的GCC / Clang都返回预期的(太小:0)。当编译为armv7时,意外输出来自Xcode工具链中的Clang。
如果您想重现:
这是确切的编译命令:ival < INT_MIN
这是Xcode 4.3.2。
我将生成的/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -arch armv7 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.1.sdk test-int.c
复制到我的iPhone并执行了。
如果有人对由此生成的汇编程序代码感兴趣:
a.out
答案 0 :(得分:5)
这是一个错误。 {C}标准中too small
没有空间为0以外的任何其他内容。以下是它的工作原理:
由于INT_MIN
是int
,因此在“通常的算术转换”期间它会转换为long
。发生这种情况是因为long
的排名高于int
(两者都是签名类型)。由于所有操作数的排名至少为int
,因此不会进行任何促销。未调用未定义或实现指定的行为。
转换期间,会保留INT_MIN
的值。由于它已从int
转换为long
,并且保证long
的范围至少为int
,因此INT_MIN
的值必须为转换期间保留。未调用未定义或实现指定的行为。不允许进行模块化转换,仅适用于无符号类型。
比较结果应为0
。
没有摆动符号扩展或其他此类事物的余地。此外,由于对printf
的调用是正确的,因此没有问题。
如果您可以在其他系统上重现它,或将其发送给可以重现它的其他人,您应该直接向您的工具链供应商报告该错误。
尝试重现该错误:我无法重现以下任何组合的行为,所有这两种组合都有优化开启和关闭:
答案 1 :(得分:1)
这是什么印刷品?
#include <limits.h>
printf("%016ld\n", LONG_MAX);
long l_int_min = (long)INT_MIN;
printf("%016lx\n", l_int_min);
我想知道INT_MIN
是否在没有签名延伸的情况下被强制转移到long
。这将使0小于结果值。
编辑:好的,第一个printf()
的结果是0000002147483647
,这意味着long
在该平台上是32位,就像int
一样。因此,将int
投射到long
实际上不应该改变任何内容。
我尝试保留“这是一个编译器错误”作为最后的手段,但这对我来说看起来像编译器错误。