将“bool”转换为“u8”

时间:2016-04-28 20:07:23

标签: rust

以下代码适用于amd64上的Rust 1.8。

use std::mem;

fn main() {
    let f: u8 = unsafe { mem::transmute(false) };
    let t: u8 = unsafe { mem::transmute(true) };
    assert_eq!(0, f);
    assert_eq!(1, t);
}

我的问题是,我能否认为这一切都会有效?我试图找到关于bool表示的参考,但我只找到thisthis,但我认为这不具有权威性。

3 个答案:

答案 0 :(得分:3)

布尔表示似乎非常严格。它表示为1和0,但我想提醒一下,如果由于一些疯狂的原因,如果你盲目地假设true == <some u8 that isn't what Rust really uses>,那么你会发现一些奇怪的行为。这与你的问题的方向相反,但我认为这是重点:

fn main() {
    use std::mem;

    let b: bool = unsafe {mem::transmute(4 as u8)};

    println!("{} {} {}", b, b == true, b == false);

    if b {
        println!("evaluates true");
    }

    if !b {
        println!("evaluates false");
    }

    let x: u8 = unsafe{mem::transmute(b)};

    println!("{}", x);

    let x = b as u8;

    println!("{}", x);
}

这会在我测试的Playground上的几乎每个配置上产生不同的输出。在同一计划中频繁出现矛盾:

调试/稳定:

true true true
evaluates false
0
0

这意味着它打印为true,与true和false比较为true,但在分支中评估为false。并转变为0。

推出/稳定:

true false true
evaluates true
4
4

如果您使用C风格的bool,并且具有正确的转换行为,这可能是您所期望的。 (编辑:实际上,不是没有。它打印错误!它与其评估方式相反)。

调试/β:

true true true
evaluates false
4
4

与Debug / Stable相同,但正确转换(我认为这可能是一个已修复的错误)。

推出/β:

与发布/稳定相同

调试/日:

与Debug / Beta相同

推出/日:

与其他人的发布相同。

加成

如果您将println!("{} {} {}", b, b == true, b == false);更改为println!("{} {}", b, b == true);,则会获得不同的打印行为。

例如,在Debug / Stable:

true false
evaluates false
0
0

此外,1 as u8的转码在所有配置上按预期工作,因此不仅仅是transmute问题。

这个故事的寓意在于,虽然这不太可能改变,但是你可能手上有一个Heisenbug的Heisenbug(或者你用u8犯了一个错误并将其转换回来或改变它不安全的指针)。对于大多数情况,我可能只是坚持使用完美且安全my_bool as u8,但我知道您的用例可能会禁止此操作。

答案 1 :(得分:1)

从未采用任何RFC来定义bool的表示形式。也就是说,作为一个实际问题,它不太可能发生变化。

答案 2 :(得分:0)

自 2021 年起更新The Rust reference 现在将 bool 的内存表示定义为等于 0 或 1 的 1 字节值:

<块引用>

布尔类型的对象的大小和对齐方式均为 1。值 false 具有位模式 0x00,值 true 具有位模式 0x01。布尔类型的对象具有任何其他位模式是未定义的行为。

相关问题