(x+1)>x如何评估为0和1?

我正在学习未定义的行为,并在没有任何明确解释的情况下偶然发现了这段代码:

#include <stdio.h>
#include <limits.h>

int foo ( int x) {
    printf ("% dn" ,  x );   //2147483647
    printf ("% dn" ,  x+1 ); //-2147483648  overflow
    return ( x+1 ) > x ;      // 1 but How????
}

int main ( void ) {
    printf ("% dn" ,  INT_MAX );     //2147483647
    printf ("% dn" ,  INT_MAX+1 );   //-2147483648  overflow
    printf ("% dn" , ( INT_MAX+1 ) > INT_MAX );  //0  makes sense, since -ve < +ve
    printf ("% dn" ,  foo(INT_MAX) );  //1
    return 0;
}

在 gcc 上编译时,编译器发出警告:

警告:“int”类型的表达式中的整数溢出导致“-2147483648”

因此,显然 的值为INT_MAX+1负,这就解释了为什么(INT_MAX+1) > INT_MAX计算结果为 0。

但是,为什么(或如何)对in(x+1) > x求值为1x = INT_MAXfoo(...)

回答

当程序表现出未定义的行为时,C 标准不会预测程序将做什么。程序可能会崩溃,可能会输出奇怪的结果,或者可能看起来工作正常。

事实上,编译器通常会在假设程序不包含未定义行为的情况下工作。

在这个表达式的情况下:

( x+1 ) > x 
( x+1 ) > x 

鉴于它x具有 type int,编译器知道有符号溢出是 UB 并且在它不会发生的假设下工作。考虑到这一点,x该表达式可能为假的地方没有值,因此编译器可以优化该表达式并将其替换为值 1。

当我在 gcc 4.8.5 下运行这个程序时,我得到以下结果-O0-O1

并以下列-O2-O3

 2147483647
-2147483648
 0
 2147483647
-2147483648
 0

然后foo在后一种情况下查看程序集:

foo:
.LFB11:
    .file 1 "x1.c"
    .loc 1 4 0
    .cfi_startproc
.LVL0:
    pushq   %rbx                // first call to printf
    .cfi_def_cfa_offset 16
    .cfi_offset 3, -16
    .loc 1 5 0
    movl    %edi, %esi
    .loc 1 4 0
    movl    %edi, %ebx
    .loc 1 5 0
    xorl    %eax, %eax
    movl    $.LC0, %edi
.LVL1:
    call    printf
.LVL2:
    .loc 1 6 0                  // second call to printf
    leal    1(%rbx), %esi
    movl    $.LC0, %edi
    xorl    %eax, %eax
    call    printf
.LVL3:
    .loc 1 8 0                  // return value
    movl    $1, %eax
    popq    %rbx
    .cfi_def_cfa_offset 8
.LVL4:
    ret
    .cfi_endproc

我们可以看到这正是编译器所做的:它优化了比较并始终返回 1。

这说明了编译器如何利用未定义的行为来应用各种优化。

  • @avm The overhead of noticing undefined behaviour would be a massive loss. By design, C++ assumes you know what you're doing.
  • @avm • **undefined behavior** is not a compiler problem, it's a programmer problem. C and C++ are not nanny languages. They presume the programmer knows what they are doing, and never lie to the compiler, and never have *undefined behavior* in their code. In the real world, this translates into an abundance of <strike>bugs</strike> *job security*.
  • @avm: Other languages can and do do that. It slows down the code to always be checking for overflow. C does not do extra work that you didn't ask for.
  • @avm It doesn't detect UB. It just assumes it won't happen. That's part of what makes C fast. It's up to the programmer to not introduce UB. And `INT_MAX+1 > INT_MAX` *is* UB. The fact that you get the result you expect doesn't change that.

以上是(x+1)&gt;x如何评估为0和1?的全部内容。
THE END
分享
二维码
< <上一篇
)">
下一篇>>