C Cheatsheet
Structs and Unions
Use this C reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.
struct Declaration and Definition
// Declare a struct type struct Point { int x; int y; }; // Declare a variable at the same time struct Rectangle { int width; int height; } rect1, rect2; // Usage struct Point p; p.x = 3; p.y = 4; struct Point q = {10, 20}; // positional initializer struct Point r = {.x = 10, .y = 20}; // designated initializer (C99+)
typedef with struct
// Separate typedef struct Node { int data; struct Node *next; // self-referential — must use struct tag here }; typedef struct Node Node; // Combined (common idiom) typedef struct { float x; float y; float z; } Vec3; Vec3 v = {1.0f, 2.0f, 3.0f}; printf("%f\n", v.x);
Member Access
struct Point p = {3, 4}; struct Point *pp = &p; p.x // access member of struct object pp->x // access member via pointer (equivalent to (*pp).x) (*pp).y // same as pp->y
Struct Initialization
typedef struct { int id; char name[64]; double score; int active; } Student; // Positional Student s1 = {1, "Alice", 95.5, 1}; // Designated (C99+) — order-independent, unspecified fields = 0 Student s2 = {.name = "Bob", .score = 88.0, .id = 2}; // Zero-initialize all fields Student s3 = {0}; // Compound literal (anonymous temporary) Student *sp = &(Student){.id = 3, .name = "Carol", .score = 91.0};
Nested Structs
typedef struct { float x, y; } Point2D; typedef struct { Point2D origin; Point2D size; } Rect; Rect r = {{0, 0}, {100, 50}}; r.origin.x = 10; printf("%f\n", r.size.y); // Pointer to nested Rect *rp = &r; rp->origin.y = 20;
Arrays of Structs
Student students[3] = { {1, "Alice", 95.5, 1}, {2, "Bob", 88.0, 1}, {3, "Carol", 91.0, 0}, }; for (int i = 0; i < 3; i++) { printf("%s: %.1f\n", students[i].name, students[i].score); } // Dynamic array Student *roster = malloc(n * sizeof(Student)); roster[0].id = 1; free(roster);
Passing Structs to Functions
// By value — function gets a copy void print_point(struct Point p) { printf("(%d, %d)\n", p.x, p.y); } // By pointer — function can modify, and no copy overhead void translate(struct Point *p, int dx, int dy) { p->x += dx; p->y += dy; } // By const pointer — read-only, no copy double distance(const struct Point *a, const struct Point *b) { int dx = a->x - b->x, dy = a->y - b->y; return sqrt(dx*dx + dy*dy); } // Return struct by value (small structs — fine; compilers optimize) struct Point midpoint(struct Point a, struct Point b) { return (struct Point){(a.x+b.x)/2, (a.y+b.y)/2}; }
struct Padding and Size
// Compiler inserts padding for alignment struct Padded { char c; // 1 byte // 3 bytes padding int n; // 4 bytes char d; // 1 byte // 7 bytes padding double f; // 8 bytes }; // sizeof(struct Padded) is likely 24, not 14 // Pack to eliminate padding (GCC/Clang extension) struct __attribute__((packed)) Packed { char c; // 1 byte int n; // 4 bytes — unaligned, may be slow }; // sizeof == 5 // Reorder to reduce padding struct Efficient { double f; // 8 int n; // 4 char c; // 1 char d; // 1 // 2 bytes padding to align to 8 }; // Check sizes at compile time _Static_assert(sizeof(struct Packed) == 5, "");
Flexible Array Members (C99+)
struct Header { int length; char data[]; // flexible array member — must be last }; struct Header *h = malloc(sizeof(struct Header) + 20); h->length = 20; h->data[0] = 'A'; free(h);
union
All members share the same memory. The size equals the largest member.
union Data { int i; float f; char bytes[4]; }; union Data d; d.i = 0x41424344; printf("%c\n", d.bytes[0]); // prints 'D' on little-endian ('A' on big-endian) // Only the last-written member should be read (others are UB in C++ but OK in C) d.f = 3.14f; printf("%f\n", d.f); // ok printf("%d\n", d.i); // type-punning: valid in C, reads float bits as int
Tagged Union (Discriminated Union)
typedef enum { TYPE_INT, TYPE_FLOAT, TYPE_STRING } Tag; typedef struct { Tag tag; union { int i; float f; char *s; } value; } Variant; void print_variant(const Variant *v) { switch (v->tag) { case TYPE_INT: printf("%d\n", v->value.i); break; case TYPE_FLOAT: printf("%f\n", v->value.f); break; case TYPE_STRING: printf("%s\n", v->value.s); break; } }
Anonymous Structs and Unions (C11+)
// Anonymous union inside struct — members accessed directly typedef struct { int type; union { int ival; float fval; char *sval; }; // no name — ival/fval/sval accessed on the outer struct } Value; Value v; v.type = 0; v.ival = 42; // no "v.u.ival" needed
Bit Fields
struct Flags { unsigned int read : 1; // 1 bit unsigned int write : 1; // 1 bit unsigned int execute : 1; // 1 bit unsigned int level : 4; // 4 bits unsigned int : 0; // force new storage unit unsigned int extra : 8; }; struct Flags f = {0}; f.read = 1; f.level = 7; // max value for 4 bits // Bit fields cannot be addressed with & // Layout is implementation-defined — avoid for portable wire formats
struct vs union Memory
struct S { int a; int b; }; // sizeof = 8 (both stored) union U { int a; int b; }; // sizeof = 4 (share same 4 bytes) struct S s; s.a = 1; s.b = 2; // both accessible simultaneously union U u; u.a = 1; u.b = 2; // u.b overwrites u.a (same memory)
Forward Declaration
// Forward declare to use in pointers before full definition struct Node; // incomplete type struct Node *create_node(void); // pointer is fine // Full definition later struct Node { int data; struct Node *next; };