以下代码适用于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
表示的参考,但我只找到this和this,但我认为这不具有权威性。
答案 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
。布尔类型的对象具有任何其他位模式是未定义的行为。