Reading — step 1 of 5
Learn
Structs
Arrays collect many of the same thing; structs collect the different parts of one thing. It's C's only tool for building compound types — no classes, no objects — and paired with functions and pointers it turns out to be enough: most of the abstractions you know from "bigger" languages are structs wearing conventions.
Defining and using
struct Point {
double x;
double y;
};
struct Point p = {3.0, 4.0}; /* positional init */
struct Point q = {.x = 1.0, .y = 2.0}; /* designated init — clearer, use it */
p.x = 10.0; /* dot: access a member */
double dx = p.x - q.x;
The type's full name is struct Point — the keyword travels with it (a typedef can shorten it; you'll see both styles constantly in real code). Members are laid out in order, adjacently in memory — a struct is a little contiguous record, the same honest bytes-in-a-row story as arrays.
Structs are values
Assignment copies the whole thing, member by member:
struct Point a = {1, 2};
struct Point b = a; /* full copy */
b.x = 99;
printf("%f\n", a.x); /* 1.0 — a untouched */
Same for function calls: pass a struct, the function gets a copy (all of chapter 4 applies). For a two-double Point, copying is cheap and good — no aliasing surprises. For big structs, or when the function must modify the original, pass a pointer — which brings us to C's best piece of syntactic sugar:
The arrow
void moveRight(struct Point *p, double dist) {
p->x += dist; /* p->x ≡ (*p).x — follow pointer, take member */
}
moveRight(&pt, 5.0);
-> exists because (*p).x is miserable to type and the pattern is everywhere: pointer-to-struct is the default calling convention for anything non-trivial. Reading rule: dot when you hold the struct, arrow when you hold its address. Miss it and the compiler's error (request for member in something not a structure) at least points at the right line.
This function-taking-struct-pointer shape — moveRight(&pt, …), player_heal(&p, 20) — is, honestly, most of what "methods" are: the pointer parameter that OO languages spell this and pass invisibly, C spells out loud. Once you see it, object systems stop being magic.
Structs compose
struct Circle {
struct Point center; /* structs nest */
double radius;
};
struct Circle c = {{0, 0}, 5.0};
c.center.x /* chained dots */
Records of records — plus arrays of structs (struct Point path[100];) — cover an enormous amount of real modeling before anything fancier is needed.
Your exercise: Point Distance Squared
Read two points, print the squared distance: (x₂−x₁)² + (y₂−y₁)² — no square root, which neatly sidesteps floating-point formatting if the inputs are integers (check the examples: they decide int members with %d versus double with %lf/%f, chapter 1's asymmetry included). Structure it like you mean it: a struct Point, a function taking two of them (by value — they're small) returning the squared distance, main doing only I/O. Scanning into members works exactly like variables: scanf("%lf %lf", &p.x, &p.y) — the & reaches inside structs just fine.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…