繁体   English   中英

位向量运算和Endianess

[英]Bit vector operations and Endianess

我在软件中做了很多位向量运算。 例如:假设我需要存储有关候选'n'的布尔信息,请执行以下操作:

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可能是这里的罪魁祸首,但我无法解释。 有什么办法可以检查吗? 这种位向量操作通常在字节顺序上安全且在整个体系结构中是否安全?

我还看到在代码的某处,我在同一位候选人的另一个位向量中设置了一些其他信息,例如:

uint8_t byte_position = n / 8;
uint8_t bit_position = n % 8;
another_information_vector[byte_position] |= (1 << bit_position);

我通常通过将这些位向量相加来找到通用的属性集。

一般而言,如果您始终使用相同的类型(在您的情况下为uint64_t )访问位向量,并且访问数据的所有系统的字节序相同,则字节序不会成为问题。

不过,让自己放心的最简单方法是将对象的地址强制转换为char*和取消引用,这将使您一次可以按它们在内存中的排列顺序看到一个字节。

更新:我刚刚观察到您的第三段代码似乎通过执行n % 8来计算byte_position

如果您有时会写出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最高地址处的地址。 如果您习惯于从最高有效到最低有效(从左到右)进行排列,这可能与您的直觉背道而驰。

在CPU内的各种体系结构中,这肯定是字节顺序安全的。 从一种体系结构写入磁盘,然后在另一种体系结构上读回该磁盘,将取决于您如何在磁盘上进行读写。 这与将任何多字节数字写入磁盘并读回该磁盘时所遇到的问题没有什么不同。 两端必须解释相同的数字。 如果在此示例中,您只是将8个字节写入磁盘,然后在不同的字节序体系结构上读取它们,则将要交换字节。

对于大多数情况,最安全的变体是在字节级别上进行操作,因此,除数为8。OTOH在某些情况下可能不理想。 与字访问相比,有些体系结构无法直接访问字节,或者具有昂贵的访问权限。

在小字节序机器上,选择任何合理的除数(8、16、32、64)时,相同的方法不会改变。 例如,对于位索引22,字节级访问处理索引为2的字节的位6。 短字访问以1来处理短字的第6位; 等等。

在大端机上,这需要用1 << (BITS_PER_CELL-1-bit_position)或(相同) HIGHEST_BIT >> bit_position替换1 << bit_position HIGHEST_BIT >> bit_position ,其中对于uint8_t,HIGHEST_BIT是0x80;对于HIGHEST_BIT >> bit_position ,HIGHEST_BIT是0x80000000,以此类推。并且,位索引0表示字节0的MSB,与小字节顺序表示字节0的LSB的情况相反。

(在串行线路上可以看到类似的效果。在RS232或以太网中,字节是从LSB传输到MSB的。MAC地址中的单个/组位是线路上的第一个,但它是第一个八位位组的LSB。)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM