C - BitArray - 设置 uint64_t 的单个位

C - BitArray - Set single bit of uint64_t

我目前正在做一个项目,其中我需要位集。我正在为位集使用 uint64_t 的数组。

我现在的问题是,每当我想设置或检查一点时,我需要做这样的操作:

uint64_t index = 42;
bArr[index/64] |= (((uint64_t)1)<<(index%64)); 

我也可以用一些聪明的 andbitshift 操作重写除法和模运算,但我担心转换1 个。我需要这个转换,否则 1 被视为 32 位单元。如本例所示 - 没有强制转换你会得到错误的输出:

uint64_t bArr[4];                           // 256 bits 
bArr[0] = bArr[1] = bArr[2] = bArr[3] = 0;  // Set to 0

uint64_t i = 255;
bArr[i/64] = (bArr[i/64] | (((uint64_t)1)<<(i%64))); 

uint32_t i2;
for (i2 = 0; i2 < 256; i2++) {
  if ((bArr[i2/64] & (((uint64_t)1)<<(i2%64))) != 0) {
    printf("bArray[%" PRIu32 "] = 1\n", i2);
  }
}

我能以巧妙的方式绕过这个转换吗?我在想表演可能会受到 every read/write...

演员表的影响

如果我没理解错的话,您需要一个至少 64 位长的文字 1。你可以 get this 而不是只写 1 而不用任何强制转换。这将创建一个值为 1 的 unsigned long long 文字。但是,不能保证该类型不超过 64 位,因此如果您依赖它恰好是 64 位,您可能需要转换。

转换本身不会影响性能。它是一个编译时结构,告诉编译器表达式的类型。

在这种情况下,它们都是整数转换和表达式,因此应该不会对性能产生影响。

<< 运算符的结果类型是左操作数的类型(整数提升后),这就是您需要使用正确类型的原因:1int 类型但你需要输入 uint64_t.

您可以使用:

(uint64_t) 1

UINT64_C(1)  /* you have to include <stdint.h> */

1ULL  

(最后一个假设 unsigned long long 在您的系统中是 64 位的,这很可能)。

但它们都是等价的:所有这些表达式都是整数常量表达式,它们的值是在编译时计算的,而不是在 运行 时计算的。

C 为此提供了宏,它将整数常量扩展为 int_leastN_t.

类型
INTN_C(value)
UINTN_C(value)

例子

#include <stdint.h>.
bArr[index/64] |= UINT64_C(1) << (index%64);

general 中最好避免转换。有时强制转换会意外地使表达式 比预期的更窄


UINT64_C 的好处:uint_least_64_t/int_least_64_t 类型必须存在 (C99)。 int64_t/uint64_t 是可选的。