发出 128 位整数数组中的清除位
Issue clearing bits in 128 bit integer array
我对这个程序的目标是我希望能够将 1000 位分别设置为 0 或 1,为此我使用了一个 128 位整数数组。
现在的问题是当我简单地 clear_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);
}
OP 的代码未使用 1 << (k%128)
的 128 位数学运算。
确保整数数学运算至少使用 128 位数学运算。
array[k/128] &= ~(1 << (k%128));
array[k/128] &= ~((__uint128_t)1 << (k%128));
或者,以便携方式使用 unsigned
应该 unsigned
的位宽为 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));
}
最好确保 1
是 unsigned
和 1u
。
我建议使用平台寄存器的本机大小。只需比较生成的代码(在此示例中为 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));
}
我对这个程序的目标是我希望能够将 1000 位分别设置为 0 或 1,为此我使用了一个 128 位整数数组。
现在的问题是当我简单地 clear_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);
}
OP 的代码未使用 1 << (k%128)
的 128 位数学运算。
确保整数数学运算至少使用 128 位数学运算。
array[k/128] &= ~(1 << (k%128));
array[k/128] &= ~((__uint128_t)1 << (k%128));
或者,以便携方式使用 unsigned
应该 unsigned
的位宽为 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));
}
最好确保 1
是 unsigned
和 1u
。
我建议使用平台寄存器的本机大小。只需比较生成的代码(在此示例中为 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));
}