Attributes and Conditional Compilation
#[repr(...)]
#[repr(...)] is the family of representation attributes that control the memory layout, field ordering, alignment, padding, and discriminant encoding of structs, enums, and unions.
Complete Reference of #[repr(...)] Attributes
| Attribute | Applicable To | Effect on Memory Layout and ABI |
|---|---|---|
(default — repr(Rust)) |
struct, enum, union |
Compiler reorders fields to minimize padding and exploits niche bit patterns |
#[repr(C)] |
struct, enum, union |
Preserves source declaration field order and C ABI alignment/size rules |
#[repr(transparent)] |
struct, single-variant enum |
Identical layout, niches, and register-passing ABI as the single non-ZST field |
#[repr(u8)] .. #[repr(u128)], #[repr(usize)] |
enum |
Sets the enum discriminant to the specified unsigned integer type |
#[repr(i8)] .. #[repr(i128)], #[repr(isize)] |
enum |
Sets the enum discriminant to the specified signed integer type |
#[repr(align(N))] |
struct, enum, union |
Raises minimum alignment to power-of-two N ($1 \le N \le 2^{29}$) |
#[repr(packed)] / #[repr(packed(N))] |
struct, union |
Lowers maximum field alignment to 1 (or N), eliminating padding |
Valid Combinations of #[repr(...)] Modifiers
Multiple representation hints can be combined inside a single attribute (#[repr(C, align(16))]) or across stacked attributes, subject to compatibility rules:
Valid Combinations:
#[repr(C, align(64))] ---> C field order + minimum 64-byte alignment
#[repr(C, packed)] ---> C field order + 1-byte packed alignment (0 padding)
#[repr(C, u8)] ---> Data-carrying enum with C union layout + 1-byte `u8` tag
Invalid Combinations (Compile Errors):
#[repr(packed, align(8))] ---> E0587: type has conflicting packed and align hints
#[repr(transparent, C)] ---> E0692: transparent type cannot have other repr hints
use std::mem::offset_of;
#[repr(C, align(16))]
struct AlignedDescriptor {
flags: u8,
addr: u64,
}
#[repr(C, packed(2))]
struct PackedPair {
tag: u8,
value: u32,
}
#[repr(u16)]
#[derive(Debug, Clone, Copy)]
enum ProtocolCode {
Handshake = 0x0001,
KeepAlive = 0x0002,
Disconnect = 0xFFFF,
}
fn main() {
println!(
"AlignedDescriptor: size = {} B, align = {} B, addr offset = {}",
size_of::<AlignedDescriptor>(),
align_of::<AlignedDescriptor>(),
offset_of!(AlignedDescriptor, addr)
);
println!(
"PackedPair: size = {} B, align = {} B, value offset = {}",
size_of::<PackedPair>(),
align_of::<PackedPair>(),
offset_of!(PackedPair, value)
);
println!(
"ProtocolCode: size = {} B, Disconnect = {:#06x}",
size_of::<ProtocolCode>(),
ProtocolCode::Disconnect as u16
);
}
AlignedDescriptor: size = 16 B, align = 16 B, addr offset = 8
PackedPair: size = 6 B, align = 2 B, value offset = 2
ProtocolCode: size = 2 B, Disconnect = 0xffff
Conflicting packed and align Error (E0587)
Attempting to apply both packed and align(N) to the same type—or placing a #[repr(align(N))] struct inside a #[repr(packed)] struct—is rejected at compile time with E0587 because lowering alignment and raising alignment contradict one another.