C CLP study materials
C CLP study resources

C CLP: Structures, Unions, Enumerations, and Bit-fields

C CLP · Work through your exam, one topic at a time.

All guide sections

Structures, Unions, Enumerations, and Bit-fields

This domain asks you to predict object layout - padding, alignment, union overlap, bit-field packing - and to know which operations on aggregates are legal in C.

Structures

  • Members appear in declaration order with padding inserted to satisfy each member's alignment, so sizeof may exceed the sum of the member sizes.
  • offsetof(struct S, m) from <stddef.h> gives a member's byte offset; it is not valid for bit-fields.
  • Whole-struct assignment copies all members (padding bytes take unspecified values). == and != are not defined for structs; compare member by member, or use memcmp only when padding is known to match.
  • Passing or returning a struct copies it. A struct may contain a pointer to itself but not an instance of itself.

Unions and enumerations

  • A union is large enough for its largest member, and all members start at offset 0. Reading a member other than the last one written reinterprets the bytes and is implementation-defined for most type pairs.
  • An enumeration declares integer constant expressions of type int, usable as case labels and array bounds; the values must fit in int.

Bit-fields

  • unsigned int flags : 3; allocates at least three bits. Allocation order and packing are implementation-defined, and the width may not exceed the declared type's width.
  • You cannot take the address of a bit-field or apply sizeof/offsetof to one. A zero-width bit-field forces the next member to a new storage unit.

Worked example

struct S { char c; int i; char d; };

On a typical machine with four-byte int alignment: c sits at offset 0, three padding bytes follow, i occupies offsets 4–7, d sits at offset 8, and three tail padding bytes keep the array stride aligned - sizeof(struct S) == 12, not 6. Reordering the members as int i; char c; char d; usually yields 8. Every one of these numbers is implementation-defined.

Traps

  • Assuming sizeof(struct) equals the sum of member sizes, or that layout is portable - never serialize a struct by writing raw bytes across platforms.
  • Comparing structs with == (a compile error) or with memcmp when padding bytes differ.
  • Omitting the struct keyword (struct S s;, not S s;) unless a typedef was declared.
  • A signed bit-field of width 1 can hold only 0 and -1.
  • Relying on the order in which bit-fields are packed.