Почему необработанные части не соответствуют ни одному из порядков байтов?

Я пытаюсь максимально оптимизировать операцию, выполняемую над срезами u32 из массивов u8. Таким образом, я тестирую различные варианты (для циклов, итераторов, использования контейнера ByteOrder и т. д.). В рамках этих тестов я также хотел проверить, могу ли я улучшить его, используя стандартную функцию from_raw_parts. Вот мой код:

use byteorder::{ByteOrder, BigEndian, LittleEndian};
use std::io::Read;

fn main(){
let random_bytes = (0..4).map(|_| { rand::random::<u8>() }).collect::<Vec<u8>>();
let random_bytes = random_bytes.as_slice();

let view = &random_bytes as *const _ as *const u32;
let slice: &[u32] = unsafe { std::slice::from_raw_parts(view, 1) };
println!("{:x?}", slice);
println!("{:x?}", LittleEndian::read_u32(&random_bytes[0..4]));
println!("{:x?}", BigEndian::read_u32(&random_bytes[0..4]));
println!("{:x?}", &random_bytes[0..4]);
}

Я бы ожидал, что по крайней мере один из двух байтов Little или Big endian будет равен первому отпечатку, но вместо этого это не так, например. пример вывода

[d951db30]
143600ff
ff003614
[ff, 0, 36, 14] 

Что я делаю не так?


person Dominus    schedule 11.12.2020    source источник
comment
Имейте в виду, что этот код может привести к неопределенному поведению. См.: stackoverflow.com/questions/33968870/   -  person E_net4 the curator    schedule 11.12.2020
comment
@E_net42 спасибо за внимание!   -  person Dominus    schedule 11.12.2020


Ответы (1)


Проблема здесь:

let view = &random_bytes as *const _ as *const u32;

Срез — это структура из двух машинных слов, которая содержит указатель на данные и количество элементов в качестве членов. Выполняя &random_bytes, вы берете ссылку на эту структуру фрагмента (которая сама содержит указатель и длину), а не получаете базовый указатель.

У срезов есть метод as_ptr, который возвращает указатель на данные. сам. Когда вы используете его, ваш код работает правильно:

use byteorder::{ByteOrder, BigEndian, LittleEndian};
use std::io::Read;

fn main(){
    let random_bytes = (0..4).map(|_| { rand::random::<u8>() }).collect::<Vec<u8>>();
    let random_bytes = random_bytes.as_slice();
    
    let view = random_bytes.as_ptr() as *const u32;
    let slice: &[u32] = unsafe { std::slice::from_raw_parts(view, 1) };
    println!("{:x?}", slice);
    println!("{:x?}", LittleEndian::read_u32(&random_bytes[0..4]));
    println!("{:x?}", BigEndian::read_u32(&random_bytes[0..4]));
    println!("{:x?}", &random_bytes[0..4]);
}

Выход на детской площадке:

[684a2f5b]
684a2f5b
5b2f4a68
[5b, 2f, 4a, 68]
person justinas    schedule 11.12.2020
comment
Черт, это надо было видеть, большое спасибо за ваше время! - person Dominus; 11.12.2020