bool
的内存表示定义为一个1字节的值,等于0或1:
布尔类型的对象每个都有1个字节的大小和对齐方式。值false的位模式为
0x00
,true的位模式为0x01
。 对于具有布尔类型的对象使用任何其他位模式均属于未定义行为。
src/behavior-considered-undefined.md
中指定...(请参见“更改的文件”选项卡中的第一个文件) - Tim McLean布尔表示似乎非常严格。它表示为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
这意味着它打印为真,在与真和假比较时都视为真,但在分支中评估为假。并转换回0。
true false true
evaluates true
4
4
如果你使用的是C-style bool,那么这可能是你所期望的,并具有正确的转换行为。(编辑:实际上不是。它打印错误!它与其评估方式相反比较)。
true true true
evaluates false
4
4
println!("{} {} {}", b, b == true, b == false);
更改为 println!("{} {}", b, b == true);
,则会获得不同的输出行为。true false
evaluates false
0
0
1 as u8
转换在所有配置上都能正常工作,因此这不仅仅是一个 transmute
的问题。
transmute
或使用不安全指针进行更改),那么您可能会遇到一种非常棘手的 Heisenbug。对于大多数情况,我建议继续使用完全有效且安全的 my_bool as u8
。尽管我知道您的用例可能禁止这样做。从未有任何RFC采用定义bool
的表示方式。 话虽如此,实际上它很少会改变。
let f: u8 = if boolValue { 1u8 } else { 0u8 }
这样的代码相比(不确定 Rust 语法的确切形式)。但是没有使用 transmute 的版本将在不依赖于任何编译器行为的情况下工作。 - Matthias247