【发布时间】:2018-07-23 12:45:45
【问题描述】:
考虑以下程序。
#include <stdio.h>
int negative(int A) {
return (A & 0x80000000) != 0;
}
int divide(int A, int B) {
printf("A = %d\n", A);
printf("negative(A) = %d\n", negative(A));
if (negative(A)) {
A = ~A + 1;
printf("A = %d\n", A);
printf("negative(A) = %d\n", negative(A));
}
if (A < B) return 0;
return 1;
}
int main(){
divide(-2147483648, -1);
}
当它在没有编译器优化的情况下编译时,它会产生预期的结果。
gcc -Wall -Werror -g -o TestNegative TestNegative.c
./TestNegative
A = -2147483648
negative(A) = 1
A = -2147483648
negative(A) = 1
使用编译器优化编译时,会产生以下错误输出。
gcc -O3 -Wall -Werror -g -o TestNegative TestNegative.c
./TestNegative
A = -2147483648
negative(A) = 1
A = -2147483648
negative(A) = 0
我正在运行gcc version 5.4.0。
我可以在源代码中进行更改以防止编译器在-O3 下产生这种行为吗?
【问题讨论】:
-
A = ~A + 1;是 UB,如果A == INT_MIN,+1会使有符号整数溢出。 -
对于 32 位
int类型,0x7FFFFFFF + 1不是未定义行为吗? -
@mch,我认为你一针见血。我从来没有想过有符号整数溢出的行为不像无符号整数溢出。我刚刚看到this question 所以现在我知道其中的区别了。
-
@Someprogrammerdude 不,它绝对不以生成错误代码而闻名。当然,GCC 中存在编译器错误(一切都有错误),但
-O3是一个安全的默认设置,并且从根本上说,该设置中的影响正确性的错误并不比一般的 GCC 中更多。 stackoverflow.com/a/11546263/1968 -
@Voo 可以说这是似是而非。但是,除非有证据,否则在当前的编译器中根本不是这种情况(
-O3曾经是实验性的,因此存在缺陷;但已经很久没有了)。说它“已知有时会生成错误代码”是完全错误的。
标签: c gcc compiler-optimization