C 中不循环的位打包

问题描述 投票:0回答:1

我有一个无符号 32 位整数值,其中包含多组位。一组内的所有位始终相同。 每组的大小相同

n
(从 2 到 32)。组与组之间没有间隙。

我需要将这些位的每一组转换为一位。接下来,我需要如下所示打包这些位:

Bit Packing

我提出了以下 C 函数,它迭代这些位并将它们打包为 2 到 32 之间的任意

n

uint32_t PackBits(uint32_t value, uint8_t n)
{
    uint32_t res = 0;
    uint32_t mask = 1;  // Also works for: mask= 1 << n-1; mask= 1 << n-2; mask= 1 << n-3; ... ; mask= 1 << n-n; 
    uint8_t s =  0;

    do {        
        res |= (value & mask) >> s;
        mask <<= n;
        s += n-1;
    } while (mask);

    return res;
}

Q:有没有一种方法可以在 C 语言中实现这一目标,而无需循环这些位,并使用一些巧妙的乘法、加法、异或、求反等序列......?

c
1个回答
0
投票

可能它比循环更有效,因为循环不适合管道。

#define MASK(n, x) ((1 << (n + 1)) - 1) << ((x) * (n))
#define BITVAL(val, n , x) ((((val) & MASK(n,x)) == MASK(n,x))  << (x))
#define PACKBITS4(val) (BITVAL(val, 4, 0) + BITVAL(val, 4, 1) + BITVAL(val, 4, 2) + BITVAL(val, 4, 3))
#define PACKBITS5(val) (BITVAL(val, 5, 0) + BITVAL(val, 5, 1) + BITVAL(val, 5, 2))

它适用于 16 位整数,但您可以对所有可能的

n
进行硬编码。当
n
是常量表达式时,它将生成不跳转的代码,如果不是,它将跳转但不循环

https://godbolt.org/z/nzqYsee3Y

它可能会更快,但必须经过测试。

© www.soinside.com 2019 - 2024. All rights reserved.