设置和取消设置64位整数中的特定位

时间:2012-12-30 16:02:49

标签: c++ c macros 64-bit bit-manipulation

好的,我想要的是非常直接的:

  • 设置数字的第N位(=使其为'1')
  • 取消设定数字的第N位(=使其为'0')

到目前为止,这是我的代码(以2个宏的形式):

#define SETBIT(X,Y)     X|=(1ULL<<(Y))
#define UNSETBIT(X,Y)   X&=(~(1ULL<<(Y)))

他们都工作正常。事情是:

  • 有什么可以优化的吗?
  • 它可以更快吗?

(两种操作都应该每秒执行数百万次,因此性能非常重要。)

4 个答案:

答案 0 :(得分:6)

你可以通过摆脱宏来略微加快编译时间,但这就是它。比特小的速度足够快,所以它应该不是问题。

这是这样做的惯用方式,我不会改变一件事。

答案 1 :(得分:3)

这是在C中设置和清除位的标准方法。

如果您希望可能加速这些宏,您可以查看这些操作的Linux程序集实现。

例如,对于x86

http://lxr.linux.no/linux/arch/x86/include/asm/bitops.h

查找__clear_bit__set_bit内联函数。

答案 2 :(得分:2)

这些宏是最优的惯用语,因此如果要进行优化,编译器可能会识别这些表达式。

你可能获得的唯一加速是......如果有更好的选择,可以避免使用它们。如果您经常进行相同的多位操作(例如,打开位0,2和4),您可以通过执行所有这些操作来获得某些操作。单个而不是使用多个SETBIT s。

答案 3 :(得分:2)

首先,您应该将宏修复为:

#define SETBIT(X,Y)     ( (X) |= 1ULL << (Y) )
#define UNSETBIT(X,Y)   ( (X) &= ~(1ULL << (Y)) ) )

这样,像SETBIT(a, 2) + 1;这样的代码会更像预期,SETBIT(1+a, 2);会产生预期错误。

您可能永远不会以这种方式使用宏,但是额外的括号无论如何都是免费的,并且解决与宏相关的问题可以是这样的PITA,它总是将额外的(){}放在宏周围

附加:使用内联汇编和CPU进行位旋转操作,假设Y在编译时不可知,UNSETBIT可以更快,避免使用NOT ... Pseudocode:

X = X OR (0xFFFFFFFFFFFFFFFE ROL Y)

然后,虽然这些宏的效率与它一样高(C编译器应该将它们优化为理想的汇编指令),但您应该提供宏来操作几个位,例如:

#define SET2BITS(X, B1, B2)     ( (X) |= 1ULL << (B1) | 1ULL << (B2) )

在某些情况下,使用内部表达式的函数式宏也可能更有效(尽管编译器优化可能会达到相同的最终结果):

#define BITSETVAL(X, B)     ( (X) | 1ULL << (B) )