【问题标题】:Issue clearing bits in 128 bit integer array发出清除 128 位整数数组中的位
【发布时间】:2018-03-12 07:35:12
【问题描述】:

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

现在的问题是,当我简单地清除_bit(3) 时,第 35 位也被清除(反之亦然)。 3 和 35 总是一起清除,4 和 36、5 和 37 等也是如此。所以显然有一个模式。我只想清除 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);
}

【问题讨论】:

  • ~(1 &lt;&lt; (k%128)) 的任何部分都不是 __uint128_t 数学。如果您想使用 __uint128_t,则需要注意如何将 int 与它们混合。
  • 1 &lt;&lt; (k%128) --> ((__uint128_t)1) &lt;&lt; (k%128)。海事组织,使用unsigned
  • @chux 哇,谢谢老兄,你解决了我的全部问题!把它放在一个答案中,我会接受它。 ;) 另外,“使用无符号”是什么意思,我们已经在使用无符号 int128 了,不是吗?
  • 1) 考虑#define UNS_WIDTH (CHAR_BIT*sizeof(unsigned)) unsigned array [(1000 + UNS_WIDTH - 1)/UNS_WIDTH]; ... array[k/UNS_WIDTH] &amp;= 1u &lt;&lt; (k%UNS_WIDTH);
  • 我会使用自己的平台整数的本机大小(32 或 64)来代替。 .

标签: c integer bit-manipulation bit int128


【解决方案1】:

OP 的代码没有使用 1 &lt;&lt; (k%128) 的 128 位数学。 @user2357112

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

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

或者,以可移植方式使用unsignedunsigned 的位宽应为 16,32 64, 36 等。无需依赖 __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));
}

最好确保1unsigned1u

【讨论】:

    【解决方案2】:

    我建议使用平台寄存器的本机大小。只需比较生成的代码(在此示例中为 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));
    }
    

    【讨论】:

      猜你喜欢
      • 2015-11-28
      • 2011-09-03
      • 2013-08-28
      • 2013-04-11
      • 2013-07-20
      • 2014-12-05
      • 1970-01-01
      相关资源
      最近更新 更多