Transmuting `bool` to `u8`

前端 未结 2 1923
情话喂你
情话喂你 2021-01-23 04:51

The following code works correctly with Rust 1.8 on amd64.

use std::mem;

fn main() {
    let f: u8 = unsafe { mem::transmute(false) };
    let t: u8 = unsafe {          


        
相关标签:
2条回答
  • 2021-01-23 05:10

    The bool representation seems to be very strict. It is represented as 1 and 0, but I'd like to caution that if for some insane reason this changes you'll get some strange behavior if you blindly assume that true == <some u8 that isn't what Rust really uses>. This is the opposite direction to your question, but I think it makes a point:

    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);
    }
    

    This produces a different output on nearly every configuration on that Playground I tested it on. With frequent flat out contradictions within the same program:

    Debug/Stable:

    true true true
    evaluates false
    0
    0
    

    This means it prints as true, compares as true with both true and false, but evaluates in a branch as false. And transmutes back to 0.

    Release/Stable:

    true false true
    evaluates true
    4
    4
    

    This is probably what you'd "expect" if you were using a C-style bool, and has the correct transmute behavior. (Edit: actually, no it's not. It prints wrong! It compares the opposite to how it evaluates).

    Debug/Beta:

    true true true
    evaluates false
    4
    4
    

    Same as Debug/Stable, but transmutes back correctly (I assume this was probably a bug that got fixed).

    Release/Beta:

    Same as Release/Stable

    Debug/Nightly:

    Same as Debug/Beta

    Release/Nightly:

    Same as Release for others.

    Bonus

    If you change println!("{} {} {}", b, b == true, b == false); to println!("{} {}", b, b == true); you get different printing behavior.

    For instance, on Debug/Stable:

    true false
    evaluates false
    0
    0
    

    In addition, transmuting from 1 as u8 works as expected on all configurations, so it's not solely a transmute issue.


    The moral of the story is that, while this is unlikely to change, you potentially have one hell of a Heisenbug on your hands if it does (or you make a mistake with the u8 and transmute it back or change it with an unsafe pointer). For most cases, I'd probably just stick with the perfectly working and safe my_bool as u8, though I understand your use case may prohibit this.

    0 讨论(0)
  • 2021-01-23 05:12

    There was never any RFC adopted defining the representation of bool. That said, as a practical matter it's very unlikely it will change.

    0 讨论(0)
提交回复
热议问题