Structs & Data Structures · beginner · ~12 min
Group related fields into one type.
A struct groups related variables (called members or fields) under one type. Access members with . on a struct value, or -> on a struct pointer. Structs are how C programs build composite data — coordinates, records, network packets, anything with more than one piece of state.
Without structs, you'd pass 10 separate parameters every time you wanted to describe a 'user' or a 'TCP segment'. With structs, you pass one pointer and the receiver has clear, named access to each piece. Every non-trivial data structure (linked list node, hash entry, file struct) is built on structs.
Definition vs declaration. struct point { int x; int y; }; declares the layout. struct point p; makes an instance. Anonymous, named, and typedef'd. typedef struct { int x; int y; } point_t; makes point_t p; work without the struct keyword. Memory layout. Fields are stored in declaration order, with padding inserted for alignment. Pass by pointer. Always pass big structs by pointer (const point_t *p) — pass-by-value copies the whole thing.
typedef struct {
int x, y;
} point_t;
point_t a = {3, 4}; // initialise members
printf("%d,%d\n", a.x, a.y); // dot access on a value
point_t *q = &a;
printf("%d\n", q->x); // arrow access on a pointer
A struct bundles several values into one named type. Access fields with . (on a struct value) or -> (on a pointer to a struct).
C is value-typed: passing a struct to a function copies it. Pass const T * for read-only, T * for read-write.
struct point { double x, y; };
struct point p = {1.0, 2.0};
printf("%g %g\n", p.x, p.y);
struct point *q = &p;
q->x = 5.0; // same as (*q).x
struct keyword (use typedef to remove it — next lesson).== — not supported. Compare field by field, or use memcmp only if there's no padding.Use gdb's print *p to dump every member. sizeof(point_t) shows the actual size including padding — often larger than the sum of fields, which is why you can't memcmp two structs naively (the padding bytes may differ).
When malloc'ing a struct, calloc(1, sizeof(*p)) zero-initialises every field — much safer than malloc + 'remember to set every field'. Don't strcpy into a fixed-size struct member without checking the source length — that's a classic stack-smash vector.
Every C struct in <stdio.h> (FILE), <sys/socket.h> (sockaddr_in), the kernel's task_struct, every linked-list / tree / hash-table node, every protocol header.
point_t and a function double distance(point_t a, point_t b). 2. Make a struct for a 'user' with name and age, write a print function. 3. Allocate a struct on the heap, fill it, free it.Structs group related values under one named type. Use . on values, -> on pointers, calloc to zero-init, and pass big structs by pointer. They are how C grows from individual variables into real data structures.