【问题标题】:Simplify binary and and xor in C简化 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 等替换它。

标签: c binary-operators


【解决方案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 进行此操作。

    【讨论】:

      猜你喜欢
      • 2019-12-18
      • 1970-01-01
      • 1970-01-01
      • 2017-01-16
      • 1970-01-01
      • 2011-06-08
      • 1970-01-01
      • 2012-06-15
      • 1970-01-01
      相关资源
      最近更新 更多