我在我的软件中进行了大量的位 vector 运算。例如:假设我需要存储有关候选“n”的 bool 信息,我执行以下操作:
uint64_t *information_vector;
uint32_t pos = n / 64;
uint32_t bit_pos = n % 64;
information_vector[pos] |= (1 << bit_pos);
我在阅读该信息时遵循类似的程序:
uint32_t pos = n / 64;
uint32_t bit_pos = n % 64;
if (information_vector[pos] & (1 << bit_pos)) {
// do something
}
同时,我还将 information_vector 写入磁盘并再次读回。现在,我正在尝试解决一个让我做噩梦的错误,我突然意识到 Endianess 可能是这里的罪魁祸首,但我无法解释。有什么办法可以检查吗?这种位 vector 操作通常是字节序安全的并且跨架构吗?
我还发现,在代码中的某个位置,我在另一个位 vector 中为同一候选者设置了一些其他信息:
uint8_t byte_position = n / 8;
uint8_t bit_position = n % 8;
another_information_vector[byte_position] |= (1 << bit_position);
我通常通过对这些位 vector 进行“与”运算来找到常见的属性集。
最佳答案
一般来说,如果您始终使用相同的类型访问位 vector (在您的情况下是 uint64_t
),并且您访问数据的所有系统的字节序是相同的,那么字节序将不会成为一个问题。
不过,让自己放心的最简单方法是将对象的地址转换为 char*
和取消引用,这将使您按照它们在内存中的排列顺序一次看到一个字节。
更新:我刚刚观察到你的第三个代码块似乎计算 byte_position
通过这样做n % 8
。
如果您有时会写出 uint64_t
的数组,有时将其视为 uint8_t
的数组,那么如果您的系统是小尾数法,您的结果可能会出乎意料。
避免此问题的最佳方法是保持类型一致。
To make this problem more concrete, consider the following example:
#include <stdio.h>
#include <stdint.h>
int main(){
uint64_t myVector = 1 << 2; // set second bit of LSB
uint8_t * ptr = (uint8_t *) &myVector;
int i;
for (i = 0; i < 8; i++)
printf("%x\n", ptr[i]);
}
在我的小端上 x86
系统,这将打印 4
接下来是 7 0
的,因为最高有效字节存储在 uint64_t
中最高地址的地址处。 。如果您习惯于思考从最重要到最不重要、从左到右排列的位,这可能会与您的直觉相悖。
关于c - 位 vector 运算和字节顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23253779/