Keyword union

source ·
Expand description

Rust 等价于 c 风格的 union

union 在声明方面看起来像 struct,但是它的所有字段都存在于同一内存中,彼此叠加在一起。

例如,如果我们希望内存中的某些位有时被解释为 u32,有时又被解释为 f32,则可以这样写:

union IntOrFloat {
    i: u32,
    f: f32,
}

let mut u = IntOrFloat { f: 1.0 };
// 读取 union 的字段总是不安全的
assert_eq!(unsafe { u.i }, 1065353216);
// 通过任何字段进行更新都会修改所有字段
u.i = 1073741824;
assert_eq!(unsafe { u.f }, 2.0);
Run

union 上的匹配

可以在 union 上使用模式匹配。 必须使用单个字段名称,并且该名称必须与 union 字段之一的名称匹配。 就像从 union 读取一样,在 union 上进行模式匹配时也需要 unsafe

union IntOrFloat {
    i: u32,
    f: f32,
}

let u = IntOrFloat { f: 1.0 };

unsafe {
    match u {
        IntOrFloat { i: 10 } => println!("Found exactly ten!"),
        // 匹配字段 `f` 将提供 `f32`。
        IntOrFloat { f } => println!("Found f = {f} !"),
    }
}
Run

union 字段的引用

union 中的所有字段都在内存中的同一位置,这意味着对于同一生命周期,整个 union 都用一个借用。

union IntOrFloat {
    i: u32,
    f: f32,
}

let mut u = IntOrFloat { f: 1.0 };

let f = unsafe { &u.f };
// 这将不会编译,因为该字段已被借用,即使只是一成不变
let i = unsafe { &mut u.i };

*i = 10;
println!("f = {f} and i = {i}");
Run

有关 union 的更多信息,请参见 Reference