【位操作】——计算后导0的个数

作用

返回 x 的二进制下后导的 0 的个数,
ctz(count trailing zero) 计算后导 0,和 __builtin_clz 相对

    int __builtin_ctz (unsigned int x)
    Returns the number of trailing 0-bits in x, starting at the least significant bit position. If x is 0, the result is undefined.

    int __builtin_ctzl (unsigned long x)
    Similar to __builtin_ctz, except the argument type is unsigned long.

    int __builtin_ctzll (unsigned long long x)
    Similar to __builtin_ctz, except the argument type is unsigned long long.

例如

int n = 1;//1
int m = 8;//1000
__builtin_ctzll(n)  /* 结果为 0 */
__builtin_ctz(m)    /* 结果为 3 */

ARM 上实现

unsigned int __builtin_ctz(unsigned int x) {
    
    
    unsigned int count;
    asm ("rbit %0, %1\n\t"
         "clz %0, %0" : "=r" (count) : "r" (x));
    return count;
}

这段代码使用了汇编语言内联(inline assembly)来实现 __builtin_ctz 函数。以下是对代码的详细解释:

  1. asm 关键字: asm 关键字用于在C代码中嵌入汇编语言代码。

  2. `“rbit %0, %1\n\t” :这是一个汇编指令,使用 rbit 指令将输入值 x 的位序反转。 %0 和 %1 是占位符,分别表示输出和输入操作数。

  • rbit 是按位反转的, 相当于把 32位 整数的二进制表示法水平旋转 180 度
  1. “clz %0, %0” :这是另一个汇编指令,使用 clz 指令计算反转后的值中前导零的数量。 %0 表示输入和输出操作数,因为反转后的值在此时已经存储在了 %0 中。

  2. : “=r” (count) : “r” (x) :这是约束(constraint)部分,用于指定操作数的寄存器约束。 “=r” (count) 表示将 count 变量的值存储到一个通用寄存器中,并且该寄存器在指令执行后作为输出。 “r” (x) 表示将 x 变量的值存储到另一个通用寄存器中,并且该寄存器在指令执行前作为输入。

  3. return count :将计算得到的前导零的数量作为函数的返回值。

这段代码的作用是使用ARM指令集中的 rbit 和 clz 指令来计算输入值 x`的二进制表示中末尾零的数量。通过反转位序和计算前导零的方式,可以有效地实现这一功能。请注意,这段代码的实现依赖于特定的ARM架构和编译器,具体的实现细节可能因平台和编译器的不同而有所不同。

扫描二维码关注公众号,回复: 16147641 查看本文章

使用示例

#include <stdio.h>
int main()
{
    
    
    unsigned int x = 12; /* 0b00000000000000000000000000001100 in binary */
    unsigned int count = __builtin_ctz(x);
    printf("Number of trailing zeros: %u\n", count);
    return 0;
}

结果输出

Number of trailing zeros: 2

猜你喜欢

转载自blog.csdn.net/tyustli/article/details/131958505