将位插入uint16_t

时间:2013-12-26 13:02:33

标签: c bit bit-shift

在使用bit时,是否有任何有效的算法允许将位index插入位置uint16_t?我已经尝试在index之后逐位读取,将所有这些位存储到char的数组中,在index处更改位,增加index,然后再次循环,从数组中获取位,但可能有更好的方法吗?所以我知道如何获取,设置,取消设置或切换特定位,但我认为可能有比逐位处理更好的算法。

uint16_t bit_insert(uint16_t word, int bit, int index);
bit_insert(0b0000111111111110, 1, 1); /* must return 0b0100011111111111 */

P.S。解决方案必须是纯ANSI兼容的C.我知道0b前缀可能特定于gcc,但我在这里使用它来使事情变得更加明显。

3 个答案:

答案 0 :(得分:4)

使用按位运算符:

#define BIT_INSERT(word, bit, index)  \
    (((word) & (~(1U << (index)))) | ((bit) << (index)))

答案 1 :(得分:1)

#include <errno.h>
#include <stdint.h>

/* Insert a bit `idx' positions from the right (lsb). */
uint16_t
bit_insert_lsb(uint16_t n, int bit, int idx)
{
    uint16_t lower;

    if (idx > 15) {
        errno = ERANGE;
        return 0U;
    }

    /* Get bits 0 to `idx' inclusive. */
    lower = n & ((1U << (idx + 1)) - 1);

    return ((n & ~lower) | ((!!bit) << idx) | (lower >> 1));
}

/* Insert a bit `idx' positions from the left (msb). */
uint16_t
bit_insert_msb(uint16_t n, int bit, int idx)
{
    uint16_t lower;

    if (idx > 15) {
        errno = ERANGE;
        return 0U;
    }

    /* Get bits 0 to `16 - idx' inclusive. */
    lower = n & ((1U << (15 - idx + 1)) - 1);

    return ((n & ~lower) | ((!!bit) << (15 - idx)) | (lower >> 1));
}

位通常从最右端(最低有效位(lsb)所在的位置)向左计数,其中最高有效位(msb)位于此处。我允许通过创建两个函数从任一侧插入。根据问题,预期的是bit_insert_msb

这两个函数执行完整性检查,将errno设置为ERANGE,如果idx的值太大,则返回0。我还为_Bool语句中的bit参数提供了一些C99的return行为:0为0,任何其他值为1.如果使用C99编译器,我建议将bit的类型更改为_Bool。然后,您可以直接将(!!bit)替换为bit

我想说它可以进行优化,但这很可能会让它变得难以理解。

快乐的编码!

答案 2 :(得分:0)

如果您正在计算左侧的位

mask = (1 << (16 - index + 1)) - 1;  // all 1s from bit "index" to LSB
// MSB of word (from left to index) | insert bit at index | LSB of word from (index-1)
word = (word & ~mask) | (bit << (16 - index)) | ((word & mask) >> 1);

可能有很多方法更有效,但这种方式很容易理解