Есть ли более безопасный способ использовать объединения для преобразования между целыми числами и числами с плавающей точкой? - PullRequest
2 голосов
/ 30 марта 2020

Я пишу виртуальную машину на Rust, и у меня есть C и C ++ фон. Мне нужна функциональность типа объединения, потому что в стеке виртуальных машин я могу хранить int или float.

В C у меня было объединение:

union stack_record_t {
    int i;
    float f;
};

Я могу использовать запись как int или как float с нулевыми накладными расходами времени выполнения. У меня есть анализатор байт-кода stati c, который обнаружит ошибки типа до выполнения байт-кода, поэтому мне не нужно хранить флаг рядом с записью.

Я не знаю, хорошая ли это идея использовать союзы в Rust, потому что они небезопасны. Есть ли безопасный способ сделать это в Rust - также с нулевой стоимостью? Должен ли я просто использовать небезопасные союзы Rust?

1 Ответ

4 голосов
/ 30 марта 2020

Вы можете использовать f32::from_bits и to_bits, чтобы безопасно переосмыслить необработанные биты u32 как f32 и наоборот. Это «бесплатное» преобразование - оно не компилируется без кода (с включенной оптимизацией). Для преобразования между u32 и i32 вы можете использовать as приведений, которые также бесплатны при использовании для изменения подписи.

Мне кажется, что u32 является здесь общим знаменателем, поэтому вы можете подумать о создании struct, который содержит u32 и предоставляет методы для получения или установки соответствующего типа:

pub struct Record(u32);

impl Record {
    fn get_int(&self) -> i32 {
        self.0 as _
    }

    fn get_float(&self) -> f32 {
        f32::from_bits(self.0)
    }

    fn set_int(&mut self, value: i32) {
        self.0 = value as _;
    }

    fn set_float(&mut self, value: f32) {
        self.0 = value.to_bits();
    }
}

Сравните сгенерированный код.

См. Также


¹ Эти функции используют transmute внутренне, что интерпретирует биты так же, как при использовании объединения. Поэтому, когда они встроены оптимизатором, сгенерированный код остается тем же.

...