【问题标题】:Intrinsic to count trailing zero bits in 64-bit integers?固有地计算 64 位整数中的尾随零位?
【发布时间】:2014-01-11 21:19:13
【问题描述】:

这是对先前关于位操作的一些问题的跟进。我修改了 this site 的代码以枚举设置了 N 位的 K 的字符串(x 是设置了 K 位的当前 int64_t,并且在此代码的末尾,它是按字典顺序排列的下一个设置了 K 位的整数):

int64_t b, t, c, m, r,z;
b = x & -x;
t = x + b;
c = x^t;
// was m = (c >> 2)/b per link
z = __builtin_ctz(x);
m = c >> 2+z;
x = t|m;

只要最低有效一位在 x 的低位 DWORD 中,使用__builtin_ctz() 的修改就可以正常工作,但如果不是,则完全中断。这可以通过以下代码看出:

for(int i=0; i<64; i++) printf("i=%i, ctz=%i\n", i, __builtin_ctz(1UL << i));

为 GCC 版本 4.4.7 打印:

i=0, ctz=0
i=1, ctz=1
i=2, ctz=2

...

i=30, ctz=30
i=31, ctz=31
i=32, ctz=0

或对于 icc 版本 14.0.0 类似的东西(除了 i>32 给出随机结果,而不是零)。在这两种情况下,使用除法而不是移动 2+z 都有效,但在我的 Sandy Bridge Xeon 上慢了大约 5 倍。还有其他我应该为 64 位使用的内在函数,还是我必须做一些内联汇编程序?

谢谢!

【问题讨论】:

    标签: c++ c performance bit-manipulation intrinsics


    【解决方案1】:

    __builtin_ctz 接受 unsigned int 类型的参数,在大多数平台上是 32 位。

    如果 long 是 64 位,您可以使用 __builtin_ctzl,它采用 unsigned long。或者你可以使用__builtin_ctzll 接受unsigned long long - 在这种情况下你应该使用1ULL &lt;&lt; i 而不是1UL &lt;&lt; i

    【讨论】:

    • 太好了,谢谢。正是我在寻找的东西(关于 ULL 与 UL,你是对的。Doh!)
    猜你喜欢
    • 1970-01-01
    • 2015-07-21
    • 2011-09-03
    • 2012-07-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-12
    相关资源
    最近更新 更多