Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does an enum require extra memory size?

Tags:

rust

My understanding is that enum is like union in C and the system will allocate the largest of the data types in the enum.

enum E1 {
    DblVal1(f64),
}

enum E2 {
    DblVal1(f64),
    DblVal2(f64),
    DblVal3(f64),
    DblVal4(f64),
}

fn main() {
    println!("Size is {}", std::mem::size_of::<E1>());
    println!("Size is {}", std::mem::size_of::<E2>());
}

Why does E1 takes up 8 bytes as expected, but E2 takes up 16 bytes?

like image 539
RajV Avatar asked Dec 05 '14 21:12

RajV


People also ask

How much memory does an enum use?

On an 8-bit processor, enums can be 16-bits wide. On a 32-bit processor they can be 32-bits wide or more or less. The GCC C compiler will allocate enough memory for an enum to hold any of the values that you have declared. So, if your code only uses values below 256, your enum should be 8 bits wide.

Does enum occupy memory?

An enum does not really take any memory at all; it's understood by the compiler and the right numbers get used during compilation. It's an int, whose size is dependent on your system.

Why is enum size 4?

The size is four bytes because the enum is stored as an int . With only 12 values, you really only need 4 bits, but 32 bit machines process 32 bit quantities more efficiently than smaller quantities.


2 Answers

In Rust, unlike in C, enums are tagged unions. That is, the enum knows which value it holds. So 8 bytes wouldn't be enough because there would be no room for the tag.

like image 131
David Schwartz Avatar answered Sep 18 '22 15:09

David Schwartz


As a first approximation, you can assume that an enum is the size of the maximum of its variants plus a discriminant value to know which variant it is, rounded up to be efficiently aligned. The alignment depends on the platform.

This isn't always true; some types are "clever" and pack a bit tighter, such as Option<&T>. Your E1 is another example; it doesn't need a discriminant because there's only one possible value.

The actual memory layout of an enum is undefined and is up to the whim of the compiler. If you have an enum with variants that have no values, you can use a repr attribute to specify the total size.

You can also use a union in Rust. These do not have a tag/discriminant value and are the size of the largest variant (perhaps adding alignment as well). In exchange, these are unsafe to read as you can't be statically sure what variant it is.

See also:

  • How to specify the representation type for an enum in Rust to interface with C++?
  • Why does Nil increase one enum size but not another? How is memory allocated for Rust enums?
  • What is the overhead of Rust's Option type?
  • Can I use the "null pointer optimization" for my own non-pointer types?
  • Why does Rust not have unions?
like image 42
Shepmaster Avatar answered Sep 20 '22 15:09

Shepmaster