我通过这个简单的演示重现了这个问题:
// bool_test_func.cpp
#include <stdio.h>
void func(bool* b) {
int a = (*b ? 0 : 1);
printf("%d\n", a); // EXPECT ether 0 or 1 here
}
// bool_test.cpp
void func(bool* b);
int main() {
int n = 128;
func((bool*)&n);
return 0;
}
-O0编译并运行:
g++ -g -O0 -Wall -o bool_test bool_test.cpp bool_test_func.cpp
mikewei@maclinux:~/testing/c++$ ./bool_test
0
-O1编译并运行(意外结果):
g++ -g -O1 -Wall -o bool_test bool_test.cpp bool_test_func.cpp
mikewei@maclinux:~/testing/c++$ ./bool_test
129
当我检查-O2 ASM代码时,我认为这是一个g bug,g的优化代码总是认为bool值是ether 1或0:
00000000004005e6 :
4005e6: 48 83 ec 08 sub $0x8,%rsp
4005ea: 0f b6 37 movzbl (%rdi),%esi
4005ed: 83 f6 01 xor $0x1,%esi #just XOR the bool val
4005f0: 40 0f b6 f6 movzbl %sil,%esi
4005f4: bf 94 06 40 00 mov $0x400694,%edi
4005f9: b8 00 00 00 00 mov $0x0,%eax
4005fe: e8 9d fe ff ff callq 4004a0
400603: 48 83 c4 08 add $0x8,%rsp
400607: c3 retq
400608: 0f 1f 84 00 00 00 00 nopl 0x0(%rax,%rax,1)
40060f: 00
gcc版本4.9.2(Debian 4.9.2-10)
这是设计的行为吗?如何禁用这个错误的最佳值?谢谢〜
1 回答
不得不在那里恭敬地不同意 .
即使这是可能的,但实际上并没有错:-)
你传递一个非bool指针作为bool指针(底层项不是bool类型),我很确定这(称为类型双关语)调用未定义的行为 .
因此代码可以自由地做任何想做的事情 .
您可以将原型
void func(bool* b)
视为您同意的 Contract ,只传递指向bool
值的指针 . 如果您违反了该 Contract ,所有投注都将被取消 . 在这种特殊情况下,您的代码:告诉它将false转换为1并将true转换为0.如果要提供有效输入(
false/0
或true/1
),xor input, 1
将是正确的做法 .但是,因为你给它
128
,所以xor
会产生129
.