我在Rust中做了一些计算数学,而且我有一些大数字,我存储在24个值的数组中。我有将它们转换为字节并返回的函数,但它对u32
值不起作用,而它适用于u64
。代码示例可以在下面找到:
fn main() {
let mut bytes = [0u8; 96]; // since u32 is 4 bytes in my system, 4*24 = 96
let mut j;
let mut k: u32;
let mut num: [u32; 24] = [1335565270, 4203813549, 2020505583, 2839365494, 2315860270, 442833049, 1854500981, 2254414916, 4192631541, 2072826612, 1479410393, 718887683, 1421359821, 733943433, 4073545728, 4141847560, 1761299410, 3068851576, 1582484065, 1882676300, 1565750229, 4185060747, 1883946895, 4146];
println!("original_num: {:?}", num);
for i in 0..96 {
j = i / 4;
k = (i % 4) as u32;
bytes[i as usize] = (num[j as usize] >> (4 * k)) as u8;
}
println!("num_to_ytes: {:?}", &bytes[..]);
num = [0u32; 24];
for i in 0..96 {
j = i / 4;
k = (i % 4) as u32;
num[j as usize] |= (bytes[i as usize] as u32) << (4 * k);
}
println!("recovered_num: {:?}", num);
}
上面的代码没有从字节数组中检索正确的数字。但是,如果我将所有u32
更改为u64
,将所有4
更改为8
s,并将num
的大小从24个值减少到12,工作得很好。我假设u32
版本存在一些逻辑问题。正确运行的u64
版本可在this Rust playground中找到。
答案 0 :(得分:7)
学习如何创建MCVE是编程时的一项重要技能。例如,为什么你有一个阵列?为什么重用变量?
您的原始第一个号码是0x4F9B1BD6
,输出的第一个号码是0x000B1BD6
。
比较中间字节表明你有垃圾:
let num = 0x4F9B1BD6_u32;
println!("{:08X}", num);
let mut bytes = [0u8; BYTES_PER_U32];
for i in 0..bytes.len() {
let k = (i % BYTES_PER_U32) as u32;
bytes[i] = (num >> (4 * k)) as u8;
}
for b in &bytes {
print!("{:X}", b);
}
println!();
4F9B1BD6
D6BD1BB1
打印出k
:
for i in 0..bytes.len() {
let k = (i % BYTES_PER_U32) as u32;
println!("{} / {}", k, 4 * k);
bytes[i] = (num >> (4 * k)) as u8;
}
显示您尝试按 4 位的倍数移位:
0 / 0
1 / 4
2 / 8
3 / 12
我非常确定今天的每个通用平台都使用 8 位作为字节,而不是 4 。
这是为什么魔术数字不好。如果你已经使用常量作为值,你会更快地注意到这个问题。
因为u32在我的系统中是4个字节
每个系统上的u32
更好为4个字节 - 这就是 u32
的原因。
总的来说,不要重新发明轮子。使用byteorder crate或等价物:
extern crate byteorder;
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
const LENGTH: usize = 24;
const BYTES_PER_U32: usize = 4;
fn main() {
let num: [u32; LENGTH] = [
1335565270, 4203813549, 2020505583, 2839365494, 2315860270, 442833049, 1854500981,
2254414916, 4192631541, 2072826612, 1479410393, 718887683, 1421359821, 733943433,
4073545728, 4141847560, 1761299410, 3068851576, 1582484065, 1882676300, 1565750229,
4185060747, 1883946895, 4146,
];
println!("original_num: {:?}", num);
let mut bytes = [0u8; LENGTH * BYTES_PER_U32];
{
let mut bytes = &mut bytes[..];
for &n in &num {
bytes.write_u32::<BigEndian>(n).unwrap();
}
}
let mut num = [0u32; LENGTH];
{
let mut bytes = &bytes[..];
for n in &mut num {
*n = bytes.read_u32::<BigEndian>().unwrap();
}
}
println!("recovered_num: {:?}", num);
}