使用带有逻辑运算符的标志而不是条件语句(例如if())

时间:2012-10-22 17:14:15

标签: c optimization flags logical-operators

假设我想在设置标志时更改变量的值。一个明显的方法如下。

int a = 1, b = 2;
if(Flag)
    {
    a=b;
    Flag = false;
    }
然而,这对于执行操作所生成的代码来说是非常低效的。我发现以下代码可以减少40%的代码来执行操作。

a = ((!Flag)*a)+((Flag)*b);
Flag = false;

我的问题:我宁愿不使用乘法“*”运算符,因为乘法/除法运算符在我的目标上执行速度较慢。在不增加代码空间的情况下,还可以使用什么来加快速度?

编辑:目标设备是在kHz范围内运行的MSP430。代码空间和执行时间至关重要。编译器是IAR C

4 个答案:

答案 0 :(得分:1)

您的编译器能够比 hack 更好地优化您的代码(检查生成的程序集)。除了比较缓慢的处理器(例如PowerPC)之外,你应该避免使用它。无论如何,如果你仍然有动力,请参见here

答案 1 :(得分:1)

以下实现了您所需的逻辑,而不使用乘法或任何条件:

unsigned int mask = Flag-1;
a = (mask & a) | (~mask & b);

所以当Flag == 1时你得到

a = (0x0 & a) | (0xffff & b);

当Flag == 0时你得到

a = (0xffff & a) | (0x0 & b);

(你真的不需要一个单独的掩码变量......你可以--Flag使用Flag而不是mask,我只是认为它会使解决方案有点清楚。)

答案 2 :(得分:1)

我会这样写,不考虑微优化:

int b = 2, a = Flag ? b : 1;

Flag = false;

看看效率如何。

答案 3 :(得分:0)

您的初始代码与其获得的效果一样有效。如果您能够使用其他模糊的混淆生成更有效的代码,则编译器的优化要么配置错误,要么编写得不好。前者更有可能,但在后一种情况下,请问IAR为什么他们的编译器会生成错误的代码。不要试图通过编写混淆代码来修复编译器。

您不需要使用条件?:运算符,它应该生成完全相同的代码。

此外,我对MSP430了解不多,但它平均为16位,并且没有任何超级高级指令缓存或分支预测,如果您认为它只是愚弄自己。即使它有,你仍然不应该混淆你的代码。