好的,我想要的很简单:
- 设置数字的第 N 位(= 设为“1”)
- 取消设置数字的第 N 位(= 将其设为“0”)
到目前为止,这是我的代码(以 2 个宏的形式):
#define SETBIT(X,Y) X|=(1ULL<<(Y))
#define UNSETBIT(X,Y) X&=(~(1ULL<<(Y)))
他们都工作正常。事情是 :
- 有什么可以优化的吗?
- 它可以做得更快吗?
(这两个操作都应该每秒执行数百万次,因此性能至关重要)。
好的,我想要的很简单:
到目前为止,这是我的代码(以 2 个宏的形式):
#define SETBIT(X,Y) X|=(1ULL<<(Y))
#define UNSETBIT(X,Y) X&=(~(1ULL<<(Y)))
他们都工作正常。事情是 :
(这两个操作都应该每秒执行数百万次,因此性能至关重要)。
您可以通过摆脱宏来稍微加快编译时间,但仅此而已。位旋转足够快,所以它不应该是一个问题。
这是惯用的做法,我不会改变任何事情。
这是在 C 中设置和清除位的标准方法。
如果您想潜在地加速这些宏,您可以查看这些操作的 Linux 汇编实现。
例如,对于x86
:
http://lxr.linux.no/linux/arch/x86/include/asm/bitops.h
查找__clear_bit
和__set_bit
内联函数。
这些宏是最佳且惯用的,因此如果需要进行优化,编译器可能会识别这些表达式。
您可能获得的唯一加速是......如果有更好的选择,请避免使用它们。如果您经常执行相同的多位操作(例如,打开位 0、2 和 4),您可以通过使用单个或而不是使用多个SETBIT
s 来执行所有这些操作来获得一些好处。
首先,您应该将宏修复为:
#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... 伪代码:
X = X OR (0xFFFFFFFFFFFFFFFE ROL Y)
然后,尽管这些宏尽可能高效(C 编译器应将它们优化为理想的汇编指令),但您或许应该提供宏来操作多个位,例如:
#define SET2BITS(X, B1, B2) ( (X) |= 1ULL << (B1) | 1ULL << (B2) )
在某些情况下,使用内部表达式的类似函数的宏可能更有效(尽管编译器优化可能会获得相同的最终结果):
#define BITSETVAL(X, B) ( (X) | 1ULL << (B) )