奇怪的C整数不等式比较结果

Alb*_*ert 15 c arm

#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);
}
Run Code Online (Sandbox Code Playgroud)

这给出了输出:

ival: 0, min: -2147483648, max: 2147483647, too big: 0, too small: 1
Run Code Online (Sandbox Code Playgroud)

怎么可能?

(我实际上遇到了CPython 2.7.3中的这个问题/错误getargs.c:convertsimple.如果你查找代码,在中case 'i',有一个检查ival < INT_MIN对我来说总是如此.另见参考测试用例源.)


好吧,我现在测试了几个不同的编译器.为x86编译的GCC/Clang都返回预期的(太小:0).当为armv7编译时,意外输出来自Xcode工具链中的Clang.


如果要重现:

这是完全编译命令: /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

这是Xcode 4.3.2.

我将结果复制a.out到我的iPhone并执行它.

如果有人对由此生成的汇编程序代码感兴趣:

    .section    __TEXT,__text,regular,pure_instructions
    .section    __TEXT,__textcoal_nt,coalesced,pure_instructions
    .section    __TEXT,__const_coal,coalesced
    .section    __TEXT,__picsymbolstub4,symbol_stubs,none,16
    .section    __TEXT,__StaticInit,regular,pure_instructions
    .syntax unified
    .section    __TEXT,__text,regular,pure_instructions
    .globl  _main
    .align  2
    .code   16
    .thumb_func _main
_main:
    push    {r7, lr}
    mov r7, sp
    sub sp, #20
    movw    r0, #65535
    movt    r0, #32767
    movs    r1, #0
    movt    r1, #0
    str r1, [sp, #16]
    str r1, [sp, #12]
    ldr r1, [sp, #12]
    ldr r2, [sp, #12]
    cmp r2, r0
    movw    r0, #0
    it  gt
    movgt   r0, #1
    and r0, r0, #1
    ldr r2, [sp, #12]
    cmn.w   r2, #-2147483648
    movw    r2, #0
    it  lt
    movlt   r2, #1
    and r2, r2, #1
    mov r3, sp
    str r2, [r3, #4]
    str r0, [r3]
    mov.w   r2, #-2147483648
    mvn r3, #-2147483648
    movw    r0, :lower16:(L_.str-(LPC0_0+4))
    movt    r0, :upper16:(L_.str-(LPC0_0+4))
LPC0_0:
    add r0, pc
    blx _printf
    ldr r1, [sp, #16]
    str r0, [sp, #8]
    mov r0, r1
    add sp, #20
    pop {r7, pc}

    .section    __TEXT,__cstring,cstring_literals
L_.str:
    .asciz   "ival: %li, min: %i, max: %i, too big: %i, too small: %i\n"


.subsections_via_symbols
Run Code Online (Sandbox Code Playgroud)

Die*_*Epp 5

这是一个错误.C标准中没有任何空间too small可以是0以外的任何其他内容.以下是它的工作原理:

  1. 既然INT_MINint,它会long在"通常的算术转换"期间转换为.发生这种情况是因为long排名高于int(并且都是签名类型).没有促销活动,因为所有操作数至少具有int排名.未调用未定义或实现指定的行为.

  2. 在转换期间,INT_MIN保留值.由于它是从转换intlong,并且保证long至少具有范围int,因此INT_MIN必须在转换期间保留值.未调用未定义或实现指定的行为.不允许进行模块化转换,仅适用于无符号类型.

  3. 比较的结果应该是0.

标志延长或其他此类事物没有摆动空间.此外,由于呼叫printf是正确的,那里没有问题.

如果您可以在其他系统上重现它,或将其发送给可以重现它的其他人,您应该直接向您的工具链供应商报告该错误.

尝试重现错误:我无法重现以下任何组合的行为,所有这些都是优化开启和关闭:

  • GCC 4.0,PPC + PPC64
  • GCC 4.2,PPC + PPC64
  • GCC 4.3,x64
  • GCC 4.4,x64
  • Clang 3.0,x64

  • 我也只能使用Clang从Xcode(4.3.2)工具链中为带有-O0的arch armv7重现它.通过优化,我得到了预期的结果.看起来像一个真正的错误.我报了. (4认同)