avm*_*avm 7 c c++ undefined-behavior
我正在学习未定义的行为,并在没有任何明确解释的情况下偶然发现了这段代码:
#include <stdio.h>
#include <limits.h>
int foo ( int x) {
printf ("% d\n" , x ); //2147483647
printf ("% d\n" , x+1 ); //-2147483648 overflow
return ( x+1 ) > x ; // 1 but How????
}
int main ( void ) {
printf ("% d\n" , INT_MAX ); //2147483647
printf ("% d\n" , INT_MAX+1 ); //-2147483648 overflow
printf ("% d\n" , ( INT_MAX+1 ) > INT_MAX ); //0 makes sense, since -ve < +ve
printf ("% d\n" , foo(INT_MAX) ); //1
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在 gcc 上编译时,编译器发出警告:
警告:“int”类型的表达式中的整数溢出导致“-2147483648”
因此,显然 的值为INT_MAX+1负,这就解释了为什么(INT_MAX+1) > INT_MAX计算结果为 0。
但是,为什么(或如何)对in(x+1) > x求值为1?x = INT_MAXfoo(...)
dbu*_*ush 13
当程序表现出未定义的行为时,C 标准不会预测程序将做什么。程序可能会崩溃,可能会输出奇怪的结果,或者可能看起来工作正常。
事实上,编译器通常会在假设程序不包含未定义行为的情况下工作。
在这个表达式的情况下:
( x+1 ) > x
Run Code Online (Sandbox Code Playgroud)
鉴于它x具有 type int,编译器知道有符号溢出是 UB 并且在它不会发生的假设下工作。考虑到这一点,x该表达式可能为假的地方没有值,因此编译器可以优化该表达式并将其替换为值 1。
当我在 gcc 4.8.5 下运行这个程序时,我得到以下结果-O0和-O1:
( x+1 ) > x
Run Code Online (Sandbox Code Playgroud)
并以下列-O2和-O3:
2147483647
-2147483648
0
2147483647
-2147483648
0
Run Code Online (Sandbox Code Playgroud)
然后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
Run Code Online (Sandbox Code Playgroud)
我们可以看到这正是编译器所做的:它优化了比较并始终返回 1。
这说明了编译器如何利用未定义的行为来应用各种优化。
| 归档时间: |
|
| 查看次数: |
265 次 |
| 最近记录: |