【发布时间】:2017-09-18 05:32:27
【问题描述】:
根据我的小型研究,以下两个函数是等效的(从性能的角度来看),因为即使是非常轻微的优化 (-O1) 也会产生相同的汇编代码。
代码 1:
#define BIT_N (10)
extern unsigned int isBitSet;
unsigned int Foo() {
unsigned int res1 = 0;
if (isBitSet)
{
res1 |= ( 1u << BIT_N );
}
return res1;
}
代码 2:
#define BIT_N (10)
extern unsigned int isBitSet;
unsigned int Foo() {
unsigned int res1 = 0;
res1 |= ( (!!isBitSet) << BIT_N );
return res1;
}
Code 1 和 Code 2 的反汇编是相同的(使用 gcc 6.3 for x86_64 + 优化 -O2 编译后):
Foo():
mov edx, DWORD PTR isBitSet[rip]
xor eax, eax
test edx, edx
setne al
sal eax, 10
ret
我个人更喜欢 Code 2 的 C 版本,它看起来更干净。但它和代码 1 一样安全吗?因为我看到了一些潜在的陷阱,比如如果isBitSet 的类型为int 和BIT_N 31,那么代码res1 = ( (!!isBitSet) << BIT_N); 将导致未定义的行为。
问题:
还有其他陷阱吗? Code 1 真的比 Code 2 更安全吗? 如果是,是否有任何已知方法可以使 Code 2 更安全而无需太多开销?
【问题讨论】:
-
如果
res1 = 5一开始会怎样? -
“代码 1 和代码 2 的反汇编是相同的”。如果是,你的编译器坏了。代码 1 使用
|=,代码 2 使用=。 -
@JeremyP 但它不会改变结果。 +查看我对 tilz0R 的评论
-
@JeremyP 我修改了代码以具有相同的
|=。但这真的不是重点。 -
我发现
if (isBitSet)比(!!isBitSet)清晰得多。你应该考虑让人们更容易阅读代码而不是编译器(无论如何它似乎都明白了)。
标签: c security optimization conditional