Step 1 of 5 · Reading · ~3 min
Learn
Memory and Structs
Structs
Arrays collect many values of one type; a struct collects the different parts of one thing into a single value. By the end of this lesson you can define a struct type, build values of it, read their members, and pass them to your own functions.
Defining and building
struct Clock {
int hours;
int minutes;
};
struct Clock start = {9, 45}; /* positional: members in order */
struct Clock stop = {.hours = 11, .minutes = 5}; /* designated: named members */
printf("%d:%d\n", start.hours, start.minutes); /* 9:45 */
A member is one named field inside the struct; the dot operator start.hours reads or writes it. Members sit in memory in the order you declared them, one after another, like a small array whose slots have names and may have different types.
typedef: naming the type once
The type above is spelled struct Clock everywhere. Most C code gives it a shorter name with typedef:
typedef struct {
int w, h;
} Size;
Size box = {4, 3}; /* no `struct` keyword */
After this there is no tag called Size, only the alias. Writing struct Size box; names a type the compiler has never seen and fails with storage size of 'box' isn't known. The rule: struct Name { ... }; means you write struct Name; typedef struct { ... } Name; means you write Name.
Structs are values
Assignment and function calls copy every member:
Size a = {4, 3};
Size b = a; /* full copy */
b.w = 99;
printf("%d\n", a.w); /* 4 -- a is untouched */
So a function can take whole structs as parameters and read their members:
int minutes_between(struct Clock from, struct Clock to) {
int dh = to.hours - from.hours;
int dm = to.minutes - from.minutes;
return dh * 60 + dm;
}
Trace it with start = {9, 45} and stop = {11, 5}: dh is 11 - 9 = 2, dm is 5 - 45 = -40, and the result is 2 * 60 - 40 = 80 minutes. The negative dm is fine: each member is subtracted from the same member of the other struct, and the arithmetic sorts out the sign.
The arrow
When a function must change the caller's struct, pass its address (last lesson's pointers) and use ->:
void grow(Size *s, int by) {
s->w += by; /* s->w means (*s).w */
}
grow(&box, 2); /* box is now {6, 3} */
Dot when you hold the struct, arrow when you hold its address. Structs also nest: a member can itself be a struct, reached with chained dots like line.start.x.
The squaring trap
C has no power operator. ^ compiles, but it is bitwise XOR:
int side = 3;
printf("%d\n", side ^ 2); /* 1 -- XOR, not a square */
printf("%d\n", side * side); /* 9 -- what you meant */
Common mistakes
- Squaring with
^. For differences 3 and 4,3 ^ 2is 1 and4 ^ 2is 6, so you print 7 instead of 25. Multiply the value by itself. - Crossing members. Subtracting
a.yfromb.xmixes two axes and prints 29 instead of 25 for points (1, 2) and (4, 6). Always pair x with x and y with y. - Adding before squaring. Squaring
dx + dylets opposite signs cancel: for (0, 0) and (3, -4) it gives 1 instead of 25. - Leaving the points at
{0, 0}. Every answer becomes 0; only the identical-points test passes.
Your exercise
Complete int dist2(Point a, Point b) so it returns the squared distance between two points, and replace the two {0, 0} placeholders in main with points built from the numbers already read. The Point typedef and all input and output are done; the likeliest slip is squaring with ^.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…