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));
我也可以用一些聪明的 and 和 bitshift 操作重写除法和模运算,但我担心转换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 位,您可能需要转换。
转换本身不会影响性能。它是一个编译时结构,告诉编译器表达式的类型。
在这种情况下,它们都是整数转换和表达式,因此应该不会对性能产生影响。
<<
运算符的结果类型是左操作数的类型(整数提升后),这就是您需要使用正确类型的原因:1
是 int
类型但你需要输入 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
是可选的。
我目前正在做一个项目,其中我需要位集。我正在为位集使用 uint64_t
的数组。
我现在的问题是,每当我想设置或检查一点时,我需要做这样的操作:
uint64_t index = 42;
bArr[index/64] |= (((uint64_t)1)<<(index%64));
我也可以用一些聪明的 and 和 bitshift 操作重写除法和模运算,但我担心转换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 位,您可能需要转换。
转换本身不会影响性能。它是一个编译时结构,告诉编译器表达式的类型。
在这种情况下,它们都是整数转换和表达式,因此应该不会对性能产生影响。
<<
运算符的结果类型是左操作数的类型(整数提升后),这就是您需要使用正确类型的原因:1
是 int
类型但你需要输入 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
是可选的。