bitvec中存储大小对load方法的影响咨询
bitvec中存储大小对load操作的影响分析
问题场景
创建一个22位的bitvec,分为两个11位的块,每个块的位模式10000000011对应十进制数1027。当bitvec的存储单元设置为usize时,load方法返回预期的1027;但设置为u8时,返回结果与预期不符:
测试代码
let vec22 = bitvec![u8 /* usize */, Msb0; 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, /* next */ 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1]; // 1027, 1027 let chunks = vec22.chunks(11); let numbers = chunks .into_iter() .map(|chunk| { let number: usize = chunk.load(); println!("{} {}", chunk, number); number }) .collect::<Vec<_>>();
异常输出
[1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1] 896 // expected 1027 [1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1] 112 // expected 1027
原因解析
核心差异来自存储单元大小对位在内存中物理分布的影响,以及load方法的解析逻辑:
存储单元为
usize时:usize的位宽(64位或32位)远大于22位,整个22位向量会被存储在单个usize单元中。每个11位的块都是连续的位序列,load方法直接按Msb0位序读取这11位,解析为usize后得到预期的1027。存储单元为
u8时:
每个u8仅能存储8位,22位需要3个u8单元来存储:- 第一个
u8:存储第一个块的前8位10000000 - 第二个
u8:存储第一个块的后3位011+ 第二个块的前5位10000,即00011100 - 第三个
u8:存储第二个块的后6位000011,即00001100
此时两个11位的块都跨了多个
u8单元:第一个块跨前两个u8,第二个块跨后两个u8。load方法解析时会基于存储单元的边界拼接位序列,而非逻辑上的连续位流,导致实际读取的位序列错位,最终计算出与预期不符的数值。- 第一个
另外需要注意:bitvec的load方法更适合处理长度等于目标类型位宽且对齐到存储单元边界的位切片。当位切片长度小于目标类型或跨存储单元时,行为会受存储单元的物理分布直接影响。
内容的提问来源于stack exchange,提问作者aryzing
相关产品推荐
相关产品推荐

