简化 C 中的二进制和异或
Posted
技术标签:
【中文标题】简化 C 中的二进制和异或【英文标题】:Simplify binary and and xor in C 【发布时间】:2021-04-22 19:06:37 【问题描述】:有没有办法简化C
中的以下表达式?
result = (constant & value) ^ value;
用例是:
#define ALL_SENSORS = (BIT(0) + BIT(1) + BIT(2) + BIT(19)) # = 524295
static int get_invalid_sensors(int sensor_mask)
return (ALL_SENSORS & sensor_mask) ^ sensor_mask;
是否可以将二进制操作简化为一个,所以我不需要调用sensor_mask
两次?
【问题讨论】:
编译器擅长常量折叠,所有的编译时常量表达式都可以由编译器自己计算,只有结果会出现在生成的代码中。编译器还可以生成重用先前计算结果的代码,特别是如果它可以推断它不会在两者之间发生变化(常量永远不会)。因此,请在启用优化的情况下进行构建,并查看生成的代码。我相信它会尽可能地达到最佳状态。 @Someprogrammerdude:sensor_mask 是一个变量,所以您所说的某些内容并不完全正确!我能想到的只有'ALL_SENSORS & (~sensor_mask)' 作为优化的一般规则:你几乎不值得做这样的低级微优化。编译器几乎总是会做得更好。更不用说手写的优化往往晦涩难懂,难以阅读、理解和维护。如果您遇到性能问题,请分析优化的构建,并专注于最重要的两个(或者可能是三个)瓶颈。ALL_SENSORS
是常量吗?例如,BIT(x)
只是 (1 << (x))
,而不是像函数调用或包含 sensor_mask
的宏这样的奇怪东西?
使用int
进行按位运算几乎肯定是错误的,因此您可能想用uint32_t
等替换它。
【参考方案1】:
(~ALL_SENSORS & sensor_mask)
怎么样?
【讨论】:
这不太一样!如果 ALL_SENSORS 是 0x0f 并且 sensor_mask 是 0x08 那么这将返回 0 而不是 0x07! @Skizz(0x0f & 0x08) ^ 0x08
为 0。
哎呀,脑放屁时刻!那么它不总是0吗?
@Skizz 或者在真值表中,((0 & 0) ^ 0) == 0
、((0 & 1) ^ 1) == 1
、((1 & 0) ^ 0) == 0
、((1 & 1) ^ 1) == 0
。与(~0 & 0) == 0
、(~0 & 1) == 1
、(~1 & 0) == 0
、(~1 & 1) == 0
进行比较。它们是一样的。
@Skizz 不,它并不总是 0。例如如果sensor_mask
是 54321,那么结果就是 54320。【参考方案2】:
如果你把这个(或至少类似的)代码放入here。然后你可以看到优化的代码,例如 RISC-V 是
get_invalid_sensors: # @get_invalid_sensors
not a0, a0
and a0, a0, a1
ret
从这里你可以意识到(~ALL_SENSORS & sensor_mask)
已经足够了。但您也可以意识到编译器很可能无论如何都能够优化您的代码。
【讨论】:
【参考方案3】:表达式(ALL_SENSORS & sensor_mask) ^ sensor_mask
的目标是屏蔽sensor_mask
中不在ALL_SENSORS
中的所有位。您也可以通过~ALL_SENSORS & sensor_mask
进行此操作。
【讨论】:
以上是关于简化 C 中的二进制和异或的主要内容,如果未能解决你的问题,请参考以下文章