mirror of
https://github.com/google/comprehensive-rust.git
synced 2025-01-04 07:24:22 +02:00
Take out unnecessary code from enum size slide (#309)
The slide is way too large to comfortable use in a classroom. Instead of printing six lines of output, the instructor should carefully walk through the different examples. That way we can take the course participants with us through the explanations instead of simply showing them the end result.
This commit is contained in:
parent
b1b78a9672
commit
1feb94e02a
@ -17,20 +17,8 @@ enum Foo {
|
||||
B,
|
||||
}
|
||||
|
||||
#[repr(u32)]
|
||||
enum Bar {
|
||||
A, // 0
|
||||
B = 10000,
|
||||
C, // 10001
|
||||
}
|
||||
|
||||
fn main() {
|
||||
dbg_size!(Foo);
|
||||
dbg_size!(Bar);
|
||||
dbg_size!(bool);
|
||||
dbg_size!(Option<bool>);
|
||||
dbg_size!(&i32);
|
||||
dbg_size!(Option<&i32>);
|
||||
}
|
||||
```
|
||||
|
||||
@ -38,13 +26,44 @@ fn main() {
|
||||
|
||||
<details>
|
||||
|
||||
Key Points:
|
||||
Key Points:
|
||||
|
||||
* Internally Rust is using a field (discriminant) to keep track of the enum variant.
|
||||
* `Bar` enum demonstrates that there is a way to control the discriminant value and type. If `repr` is removed, the discriminant type takes 2 bytes, becuase 10001 fits 2 bytes.
|
||||
* As a niche optimization an enum discriminant is merged with the pointer so that `Option<&Foo>` is the same size as `&Foo`.
|
||||
* `Option<bool>` is another example of tight packing.
|
||||
* For [some types](https://doc.rust-lang.org/std/option/#representation), Rust guarantees that `size_of::<T>()` equals `size_of::<Option<T>>()`.
|
||||
* Zero-sized types allow for efficient implementation of `HashSet` using `HashMap` with `()` as the value.
|
||||
|
||||
* You can control the discriminant if needed (e.g., for compatibility with C):
|
||||
|
||||
```rust,editable
|
||||
#[repr(u32)]
|
||||
enum Bar {
|
||||
A, // 0
|
||||
B = 10000,
|
||||
C, // 10001
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println!("A: {}", Bar::A as u32);
|
||||
println!("B: {}", Bar::B as u32);
|
||||
println!("C: {}", Bar::C as u32);
|
||||
}
|
||||
```
|
||||
|
||||
Without `repr`, the discriminant type takes 2 bytes, because 10001 fits 2
|
||||
bytes.
|
||||
|
||||
|
||||
* Try out other types such as
|
||||
|
||||
* `dbg_size!(bool)`: size 1 bytes, align: 1 bytes,
|
||||
* `dbg_size!(Option<bool>)`: size 1 bytes, align: 1 bytes (niche optimization, see below),
|
||||
* `dbg_size!(&i32)`: size 8 bytes, align: 8 bytes (on a 64-bit machine),
|
||||
* `dbg_size!(Option<&i32>)`: size 8 bytes, align: 8 bytes (null pointer optimization, see below).
|
||||
|
||||
* Niche optimization: Rust will merge use unused bit patterns for the enum
|
||||
discriminant.
|
||||
|
||||
* Null pointer optimization: For [some
|
||||
types](https://doc.rust-lang.org/std/option/#representation), Rust guarantees
|
||||
that `size_of::<T>()` equals `size_of::<Option<T>>()`.
|
||||
|
||||
Example code if you want to show how the bitwise representation *may* look like in practice.
|
||||
It's important to note that the compiler provides no guarantees regarding this representation, therefore this is totally unsafe.
|
||||
|
Loading…
Reference in New Issue
Block a user