以128位整数数组发出清除位

时间:2017-09-30 17:03:35

标签: c integer bit-manipulation bit int128

我对这个程序的目标是我希望能够将1000位分别设置为0或1,因为我使用128位整数数组。

现在问题是当我只是clear_bit(3)时,第35位也被清除(反之亦然)。 3&总是清空35个,4个和4个相同。 36,5和5因此,显然有一种模式。我只想要清除3,其余的则保持1。

为什么会发生这种情况?谢谢!

#include <stdio.h>

__uint128_t array [(1000/128) + 1];

// Set bit to 0.
void clear_bit(int k)                
{
    array[k/128] &= ~(1 << (k%128));
}

// Find the value of bit.
int test_bit(int k)
{
    return((array[k/128] & (1 << (k%128) )) != 0);     
}

// Set bit to 1.
void set_bit(int k)
{
    array[k/128] |= 1 << (k%128);  // Set the bit at the k-th position in A[i]
}

int main (void)
{
    // Set all bits to 1.
    for(int i = 0; i < 40; i++) {
        set_bit(i);
    }

    // I want to clear bit 3, but it also clears 35 for an unknown reason.
    clear_bit(3);

    for(int i = 0; i < 40; i++) {
        printf("%d is now:%d\n", i, test_bit(i));
    }

    return (0);
}

result

2 个答案:

答案 0 :(得分:1)

OP的代码不使用1 << (k%128)的128位数学运算。 @user2357112

确保整数数学至少使用128位数学运算。

array[k/128] &= ~(1 << (k%128));
array[k/128] &= ~((__uint128_t)1 << (k%128));

替代方案,以unsigned的比特宽度为16,32 64,36等,以便携式方式使用unsigned。无需依赖__uint128_t

#include <limits.h>
#define UNS_WIDTH (sizeof(unsigned)*CHAR_BIT)

unsigned array[(1000 + UNS_WIDTH - 1)/UNS_WIDTH];

void clear_bit(int k) {
  array[k/UNS_WIDTH] &= ~(1u << (k%UNS_WIDTH));
}

最好通过1确保unsigned1u

答案 1 :(得分:0)

我建议使用本机大小的平台寄存器。只比较生成的代码(在本例中为64位平台) - https://godbolt.org/g/Y316vU

__uint128_t array [(1000/128) + 1];
uint64_t array1[(1000/64) + 1];

void assignBit64(unsigned bit, unsigned value)
{
    array1[bit >> 6] &= ~((uint64_t)1 << (bit & 63));
    array1[bit >> 6] |= ((uint64_t)!!value) << (bit & 63);
}

void assignBit128(unsigned bit, unsigned value)
{
    array[bit >> 7] &= ~((__uint128_t)1 << (bit & 127));
    array[bit >> 7] |= ((__uint128_t)(!!value)) << (bit & 127);
}


void resetBit64(unsigned bit)
{
    array1[bit >> 6] &= ~((uint64_t)1 << (bit & 63));    
}

void resetBit128(unsigned bit)
{
    array[bit >> 7] &= ~((__uint128_t)1 << (bit & 127));
}

void setBit64(unsigned bit)
{
    array1[bit >> 6] |= ((uint64_t)1 << (bit & 63));    
}

void setBit128(unsigned bit)
{
    array[bit >> 7] |= ((__uint128_t)1 << (bit & 127));
}