奇怪ç整数不平等的比较结果 [英] strange C integer inequality comparison result

查看:214
本文介绍了奇怪ç整数不平等的比较结果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

 的#include<&limits.h中GT;
#包括LT&;&stdio.h中GT;
诠释主(){
    长IVAL = 0;
    的printf(IVAL:李%,最小:%I,最大:%I,太大:%我,太小:%I \\ N,
           IVAL,INT_MIN,INT_MAX,IVAL> INT_MAX,IVAL< INT_MIN);
}

这给出了输出:

  IVAL:0分:-2147483648,最大:2147483647,太大:0,太小:1

这怎么可能?

(事实上,我在CPython的2.7.3这个问题/臭虫按 getargs.c convertsimple 如果你看到了code,在情况下,我,还有就是检查 IVAL< INT_MIN 这是一直对我如此。参见测试用例与源进一步引用的。)


好了,现在我测试了几个不同的编译器。 GCC /锵,编为86全部返回预期(太小:0)。意外的输出在X code工具链锵编译时的ARMv7


如果要复制:

这是确切的编译命令: /Applications/X$c$c.app/Contents/Developer/Toolchains/X$c$cDefault.xctoolchain/usr/bin/clang -arch的ARMv7 - isysroot /Applications/X$c$c.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.1.sdk测试int.c

这为X code 4.3.2。

我复制生成的的a.out 到我的iPhone并执行它。

如果有人有兴趣在此生成汇编code:

  .section伪__TEXT,__文本,定期,pure_instructions
    .section伪__TEXT,__ textcoal_nt,凝聚,pure_instructions
    .section伪__TEXT,__ const_coal,凝聚
    .section伪__TEXT,__ picsymbolstub4,symbol_stubs,无,16
    .section伪__TEXT,__ StaticInit,定期,pure_instructions
    .syntax统一
    .section伪__TEXT,__文本,定期,pure_instructions
    .globl _main
    .align伪2
    。code 16
    .thumb_func _main
_主要:
    推{R7,LR}
    MOV R7,SP
    子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
    它GT
    movgt R0,#1
    和R0,R0,#1
    LDR R2,[SP,#12]
    cmn.w R2,#-2147483648
    MOVW R2,#0
    它LT
    movlt R2,#1
    和r2,R2,#1
    MOV R3,SP
    海峡R2,[R 3,#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:
    添加R0,PC
    BLX _printf
    LDR R1,[SP,#16]
    STR R0,[SP,#8]
    MOV R0,R1
    加SP,#20
    POP {R7,PC}    .section伪__TEXT,__ CString的,cstring_literals
L_.str:
    .ascizIVAL:李%,最小:%I,最大:%I,太大:%我,太小:%I \\ N
.subsections_via_symbols


解决方案

这是一个错误。有C标准没有空间太小来是任何0以外下面是它如何工作的:


  1. 由于 INT_MIN INT ,它就会被转换成在通常的算术转换。这是因为 INT 排名较高(无一不是符号类型)。没有促销发生,因为所有的操作数都至少有 INT 军衔。没有未定义或执行指定的行为被调用。


  2. 在转换过程中, INT_MIN 的值是preserved。因为它正在从 INT 转换为,它保证了至少 INT 的价值 INT_MIN 必须在preserved转换。没有未定义或执行指定的行为被调用。没有模块化转换是允许的,那些是无符号类型只。


  3. 比较的结果应该是 0


有没有为符号扩展或其他类似的东西回旋余地。另外,由于在调用 printf的是正确的,是没有问题的存在。

如果你能重现它在另一个系统上,或将其发送给其他人谁可以复制它,你应该直接报告错误到你的工具链供应商。

尝试重现错误:我无法重现下列任何组合的行为,全部都与上下车优化:


  • GCC 4.0,PPC + PPC64

  • GCC 4.2,PPC + PPC64

  • GCC 4.3,64

  • GCC 4.4,64

  • 铛3.0,64

#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);
}

This gives the output:

ival: 0, min: -2147483648, max: 2147483647, too big: 0, too small: 1

How is that possible?

(I actually got hit by this problem/bug in CPython 2.7.3 in getargs.c:convertsimple. If you look up the code, in case 'i', there is the check ival < INT_MIN which was always true for me. See also the test case source with further references.)


Well, I tested a few different compilers now. GCC/Clang, compiled for x86 all return the expected (too small: 0). The unexpected output is from the Clang in the Xcode toolchain when compiled for armv7.


If you want to reproduce:

This is the exact compile command: /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

This is Xcode 4.3.2.

I copied the resulting a.out over to my iPhone and executed it.

If anyone is interested in the assembler code generated by this:

    .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

解决方案

This is an error. There is no room in the C standard for too small to be anything other than 0. Here's how it works:

  1. Since INT_MIN is an int, it gets converted to long during the "usual arithmetic conversions". This happens because long has higher rank than int (and both are signed types). No promotions occur, since all of the operands have at least int rank. No undefined or implementation-specified behavior is invoked.

  2. During conversion, the value of INT_MIN is preserved. Since it is being converted from int to long, and it is guaranteed that long has at least the range of int, the value of INT_MIN must be preserved during the conversion. No undefined or implementation-specified behavior is invoked. No modular conversions are permitted, those are for unsigned types only.

  3. The result of the comparison should be 0.

There is no wiggle room for sign extension or other such things. Also, since the call to printf is correct, there is no problem there.

If you can reproduce it on another system, or send it to someone else who can reproduce it, you should report the bug directly to your toolchain vendor.

Attempts to reproduce the bug: I was not able to reproduce the behavior on any of the following combinations, all both with optimization on and off:

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

这篇关于奇怪ç整数不平等的比较结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆