Rust libc为何为结构体使用repr(packed)而非repr(C)?
#[repr(packed)] instead of #[repr(C)] for structs passed to system libc? Great question! The choice to use #[repr(packed)] instead of #[repr(C)] for structs like utsname (used in the uname syscall) comes down to prioritizing strict ABI compatibility and cross-platform reliability over minor performance tradeoffs. Let’s break down the key reasons:
Strict adherence to system ABI requirements
System libc structs used in syscalls are defined by the operating system’s ABI, not just standard C rules. Many platforms’ ABIs mandate these structs have a packed, padding-free layout—no extra bytes inserted between fields for alignment. While#[repr(C)]follows the target platform’s default C compiler alignment rules, edge cases exist where a system’s actual ABI expects a layout that differs from what the local C compiler produces (e.g., some embedded systems or niche Unix variants).#[repr(packed)]eliminates ambiguity by forcing Rust to strip all padding, ensuring the struct’s memory layout exactly matches what the system syscall expects.Guaranteed cross-platform consistency
Thelibccrate supports an enormous range of platforms—from x86_64 Linux to ARM macOS to BSD variants. Different C compilers (or even different versions of the same compiler) on these platforms may have subtle padding rule differences. Using#[repr(packed)]creates a universal, padding-free layout that works across all environments, eliminating the need for platform-specific struct definitions and reducing crash or incorrect syscall risks from layout mismatches.Lessons from historical compatibility issues
Earlylibccrate versions used#[repr(C)]for many of these structs, but developers encountered cases where Rust’s interpretation of C layout rules didn’t match the system’s expected layout. For example, some platforms have non-standard padding rules for specific syscall structs that aren’t captured by standard#[repr(C)]. Switching to#[repr(packed)]resolved these problems by ensuring the struct’s layout aligns perfectly with system expectations, regardless of platform.Performance is a secondary concern
While unaligned loads can incur a performance penalty on some architectures (like x86, though it’s often minimal), syscall structs are typically small (e.g.,utsnamewith short string fields). The overhead of the syscall itself is orders of magnitude larger than any unaligned access cost. For thelibccrate, correctness and cross-platform reliability are far more critical than squeezing out tiny performance gains from aligned memory access.
Note that this choice isn’t universal—only structs directly passed to system syscalls (where ABI layout is rigidly defined) use #[repr(packed)]. Other libc structs used only within C code (not direct syscalls) may still use #[repr(C)] where appropriate.
内容的提问来源于stack exchange,提问作者bornfree

