将数字基元(i32,f64等)转换为字节表示

Ror*_*ory 26 types rust

我正在编写一个库,用于对二进制格式的数据进行编码/解码.格式的一部分是数字,我使用锈病的本地原始类型(如i8,i64,f32等).

是否有这些数据类型转换成/二进制,即转换为一个简单的,内置的方式f64/ f32/ i64/等.变成了Vec<u8>?同样有没有办法将4 u8秒(在一个Vec<u8>说法中)转换为f32

Nic*_*hel 27

从Rust 1.32开始,您可以使用{to,from}_{ne,le,be}_bytes整数类型。

let begin = 1234_i32;
let bytes = begin.to_ne_bytes();
let and_back = i32::from_ne_bytes(bytes);
Run Code Online (Sandbox Code Playgroud)

对于浮点,您仍然必须依靠先前的方法。


Vla*_*eev 21

不幸的是,目前没有安全的内置支持从Rust中读取/写入一个字节数组的原语.有几个社区库,但是,字节顺序是最常用的:

extern crate byteorder;

use byteorder::{LittleEndian, WriteBytesExt};
use std::mem;

fn main() {
    let i: i64 = 12345;
    let mut bs = [0u8; mem::size_of::<i64>()];
    bs.as_mut()
        .write_i64::<LittleEndian>(i)
        .expect("Unable to write");

    for i in &bs {
        println!("{:X}", i);
    }
}
Run Code Online (Sandbox Code Playgroud)

当然,你总是可以投射原始指针.例如,你可以把*const i64*const i8,然后将其转换成相应的字节片&[u8].但是,这很容易出错,unsafe并且由于endiannness而依赖于平台,因此它应该仅作为最后的手段使用:

use std::{mem, slice};

fn main() {
    let i: i64 = 12345;
    let ip: *const i64 = &i;
    let bp: *const u8 = ip as *const _;
    let bs: &[u8] = unsafe { slice::from_raw_parts(bp, mem::size_of::<i64>()) };

    for i in bs {
        println!("{:X}", i);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • `byteorder`完全解决了它.当我说"内置"时,我应该指明来自crates.io的东西就足够了. (3认同)
  • 使用`std :: slice :: from_raw_parts`代码较少,也标记为稳定.但是出于同样的原因仍然不安全! (2认同)

F00*_*001 15

std::mem::transmute可以使用,虽然它是unsafe:

fn main() {
    let var1 = 12345678_i64;
    let raw_bytes: [i8; 8] = unsafe { std::mem::transmute(var1) };
    for byte in &raw_bytes {
        println!("{}", byte);
    }
}
Run Code Online (Sandbox Code Playgroud)

注意:请确保两个变量的大小完全相等.

  • 可以通过使用`std :: mem :: size_of :: &lt;i64&gt;()`而不是数组中的`8`来确保正确的大小。 (2认同)

Mic*_*pse 9

尼古拉斯·里舍尔Nicholas Rishel)的答案为基础

拉斯特1.32有:{to,from}_{ne,le,be}_bytesto_bits,和from_bits

将整数转换为字节然后返回:

let x = 65535_i32;
let x_bytes = x.to_ne_bytes();                  // x_bytes = [255, 255, 0, 0] or [0, 0, 255, 255]
let original_x = i32::from_ne_bytes(x_bytes);   // original_x = 65535 = x
Run Code Online (Sandbox Code Playgroud)

将浮点数转换为字节然后返回:

let y = 255.255_f64;
let y_bytes = y.to_bits().to_ne_bytes();
let original_y = f64::from_bits(u64::from_ne_bytes(y_bytes)); // original_y = 255.255 = y
Run Code Online (Sandbox Code Playgroud)

根据Rust文档from_bits可能存在可移植性问题

每晚生锈:

Rust每晚{to,from}_{ne,le,be}_bytes为浮点类型添加:issue

将浮点数转换为字节,然后返回(每晚):

#![feature(float_to_from_bytes)]

let y = 255.255_f64;
let y_bytes = y.to_ne_bytes();
let original_y = f64::from_ne_bytes(y_bytes); // original_y = 255.255 = y
Run Code Online (Sandbox Code Playgroud)