假设我想在设置标志时更改变量的值。一个明显的方法如下。
int a = 1, b = 2;
if(Flag)
{
a=b;
Flag = false;
}
然而,这对于执行操作所生成的代码来说是非常低效的。我发现以下代码可以减少40%的代码来执行操作。
a = ((!Flag)*a)+((Flag)*b);
Flag = false;
我的问题:我宁愿不使用乘法“*”运算符,因为乘法/除法运算符在我的目标上执行速度较慢。在不增加代码空间的情况下,还可以使用什么来加快速度?
编辑:目标设备是在kHz范围内运行的MSP430。代码空间和执行时间至关重要。编译器是IAR C
答案 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位,并且没有任何超级高级指令缓存或分支预测,如果您认为它只是愚弄自己。即使它有,你仍然不应该混淆你的代码。