要将u32
转换为它的字节,我知道已经有了:
u32::to_le_bytes
u32::to_be_bytes
u32::to_ne_bytes
u32::from_le_bytes
u32::from_be_bytes
u32::from_ne_bytes
但是,是否有任何可靠的跨平台方法将&mut u32
转换为其字节的引用,如&mut u8
?
像这样:
fn as_be_bytes_mut(num: &mut u32) -> [&mut u8; 4] {
todo!()
}
fn main() {
let mut num: u32 = 0x12345678;
// Prints `0x12345678 - [12, 34, 56, 78]`
println!("{:#x} - {:x?}", num, num.to_be_bytes());
let parts = as_be_bytes_mut(&mut num);
*parts[2] = 0xfe;
// Should print `0x1234fe78 - [12, 34, fe, 78]`
println!("{:#x} - {:x?}", num, num.to_be_bytes());
}
其基本原理是理论上应该是可能的,因为无论如何修改其底层字节,u32
都没有无效状态。
尝试:
fn as_ne_bytes_mut(num: &mut u32) -> [&mut u8; 4] {
unsafe {
let ptr: *mut u8 = (num as *mut u32).cast();
[
&mut *ptr.add(0),
&mut *ptr.add(1),
&mut *ptr.add(2),
&mut *ptr.add(3),
]
}
}
fn main() {
let mut num: u32 = 0x12345678;
println!("{:#x} - {:x?}", num, num.to_be_bytes());
let parts = as_ne_bytes_mut(&mut num);
*parts[1] = 0xfe;
println!("{:#x} - {:x?}", num, num.to_be_bytes());
}
0x12345678 - [12, 34, 56, 78]
0x1234fe78 - [12, 34, fe, 78]
我认为(tm)这是合理的,因为u32
是u8
的打包数组,u8
总是正确对齐的,生存期也应该匹配。我还没有找到实现as_be/le_bytes_mut的方法。我也不是100%肯定这是声音,所以一些反馈会有所帮助。
3条答案
按热度按时间xxe27gdn1#
它 * 应该 * 是健全的得到一个
&mut [u8; 4]
了。这比
[&mut u8; 4]
好得多,因为它是无操作的。但是,您将无法创建le
和be
版本,除非您交换位并返回一个impl DerefMut<Target = &mut [u8; 4]>
保护,该保护在丢弃时将位交换回来。我可能会使用四个函数,每个函数返回一个字节,而不是返回
[&mut u8; 4]
的le
和be
函数。虽然如果你使用它们相同,他们应该优化到相同的东西。米莉认为这些都很好,至少。您可以使它们成为一个单一的const泛型函数,但给予在
0..4
范围内将不太符合人体工程学。(playground)mnemlml82#
这可以在
cfg(target_endian = "...")
的帮助下实现:虽然它看起来有点复杂,但编译器设法optimize it perfectly:
vu8f3i0k3#
不需要指针运算也可以做到这一点。
代码:
它也编译成了一个很好的汇编:神栓链接。