Structs: Declaration, Access, Padding, Alignment
This chapter introduces struct, C's mechanism for grouping related values into a single object, and explains the padding and alignment rules that determine how structs are laid out in memory.
Why This Matters
Structs are the foundation of every nontrivial C program. Padding and alignment decide sizeof(struct), affect performance, and matter enormously for binary compatibility, file formats, network protocols, and FFI.
Prerequisites
c.core.7— lifetime and storage.c.core.21— arrays and decay.
Core Concept
What a struct is
A struct is a composite object type containing a sequence of named members. Each member has its own type and storage.
struct Point {
int x;
int y;
};
struct Point is a type; struct Point p; declares an object of that type.
Member access
struct Point p;
p.x = 1;
p.y = 2;
struct Point *q = &p;
q->x = 3; /* equivalent to (*q).x */
The . operator accesses a member of a struct; -> accesses a member through a pointer.
Padding and alignment
Each type has an alignment requirement (a power of two, typically). A struct's members are laid out in declaration order, and the compiler inserts padding between members (and possibly after the last member) so that each member is properly aligned. The struct's own alignment is the maximum of its members' alignments.
struct Example {
char c; /* 1 byte */
int i; /* 4 bytes, must be 4-aligned -> 3 bytes padding before */
};
/* sizeof(struct Example) is 8 on typical systems */
Syntax
Declaration and definition
struct Name {
type member1;
type member2;
};
struct Name object;
struct Name *ptr = &object;
Initialization
struct Point p = {1, 2}; /* positional */
struct Point q = {.x = 1, .y = 2}; /* designated (C99) */
Anonymous struct (C11)
struct Outer {
int a;
struct { int b; int c; }; /* anonymous struct member */
};
Members of an anonymous struct are accessed as if they were members of the enclosing struct (o.b, not o.inner.b).
Examples
Struct with padding
#include <stdio.h>
#include <stddef.h>
struct S {
char c;
int i;
};
int main(void)
{
printf("sizeof(struct S) = %zu\n", sizeof(struct S));
printf("offsetof(struct S, c) = %zu\n", offsetof(struct S, c));
printf("offsetof(struct S, i) = %zu\n", offsetof(struct S, i));
return 0;
}
Expected output (typical LP64):
sizeof(struct S) = 8
offsetof(struct S, c) = 0
offsetof(struct S, i) = 4
offsetof is defined in <stddef.h>.
Copying and returning structs
struct Point a = {1, 2};
struct Point b = a; /* whole-struct copy */
Structs can be assigned, passed by value, and returned by value. The entire struct (including padding, in the abstract machine) is copied.
How It Works
The compiler assigns each member an offset that is a multiple of the member's alignment. It inserts padding bytes where necessary. The struct size is rounded up to a multiple of the struct's alignment so that arrays of the struct keep each element aligned.
Variations
Packing
Compilers offer pragmas or attributes to pack structs (remove padding):
/* GCC/Clang */
struct __attribute__((packed)) S {
char c;
int i;
};
Packed structs remove padding but can create misaligned accesses (slower, and UB if dereferenced through a misaligned pointer). Use only for file/network/register layouts where the format is fixed. COMPILER-SPECIFIC
Flexible array members (later)
c.struct.fam covers structs whose last member is an array of unspecified size.
Opaque structs (later)
c.struct.decl introduces forward declarations; opaque structs are covered with multi-file programs in c.core.39.
Common Mistakes
- Assuming
sizeof(struct)equals the sum of member sizes (padding breaks
this).
- Assuming members are laid out without gaps.
- Assuming a particular member order in memory (it is declaration order, but
with padding inserted).
- Casting a packed struct pointer to a normally aligned pointer and
dereferencing it.
Undefined Behavior
- Accessing a struct through a pointer of an incompatible type (strict
aliasing). VERIFIED
- Dereferencing a misaligned pointer (e.g., from a packed struct's member).
VERIFIED
- Accessing a struct object outside its lifetime.
Portability
- Padding, alignment, and
sizeofare implementation-defined.VERIFIED - Member order is guaranteed (declaration order), but offsets are not.
offsetofis the portable way to query member offsets.- Packing is a compiler extension, not ISO C.
Under the Hood
Struct layout is computed by the compiler and baked into every member access as an offset. Member access p->x compiles to a load/store at p + offsetof(T, x). Padding bytes are not read or written by normal member access, though whole-struct copy copies them in the abstract machine.
Practical Usage
- Use structs to group related data and to define APIs.
- Use
offsetofandsizeoffor portable layout reasoning. - Avoid packed structs except for fixed binary layouts; prefer explicit
serialization for portable data exchange.
Exercises
1. Define a struct with mixed member sizes and print sizeof and each offsetof. Explain every padding byte. 2. Write a function that copies a struct by value and verify it works. 3. Demonstrate -> vs . access. 4. Use a packed struct and observe the change in sizeof (and any warnings).
Deep Challenge
Given this struct, compute sizeof, each member offset, and the total padding on a typical LP64 system, and explain your reasoning:
struct Mixed {
char a;
double b;
char c;
int d;
};
Then verify with offsetof and sizeof.
Related Concepts
c.obj.alignment— alignment in depth.c.struct.fam— flexible array members.c.ffi.struct-layout— struct layout in FFI.c.sec.5— how padding matters for security.
References
- ISO/IEC 9899:2018 §6.7.2.1 (struct/union), §6.2.8 (alignment), §7.19
(stddef.h offsetof).
Verification
- Struct members are laid out in declaration order with padding.
VERIFIED - Struct size rounded up to alignment.
VERIFIED offsetofis standard.VERIFIED- Packing is a compiler extension.
VERIFIED - No example was executed during generation unless noted. `Execution not
verified.`
Progress
- [ ] Read
- [ ] Understand
- [ ] Complete examples
- [ ] Complete exercises
- [ ] Complete deep challenge
Concept checkboxes
- [ ] Struct declaration
- [ ] Member access (. and ->)
- [ ] Padding
- [ ] Alignment
- [ ] offsetof
- [ ] Struct copying/assignment/return
- [ ] Packing
Mastery levels
| Concept | Current level (0–8) | Target level |
|---|---|---|
| c.struct.decl | 0 | 6 |
| c.struct.padding | 0 | 6 |
| c.struct.alignment | 0 | 6 |