C Tutorial
C Structures
struct groups related fields under one name: a point, a player, a record.
Related fields, one type
An array stores many values of one type. A struct stores a handful of values that belong together, even if the types differ. A point on a map has an x and a y. A player has a name and a score. Those are not four loose variables. They are one record.
You name the shape first. Then you create variables of that shape. Each variable is a struct object with its own copy of the fields. In C you keep the word struct when you declare a variable:struct Point p;. A later chapter covers typedef, which can shorten that.
Define a struct
The keyword struct, a type name, a brace block of fields, and a semicolon after the closing brace. That last semicolon is easy to forget. The compiler will complain on the next line.
Example
#include <stdio.h>
struct Point {
double x;
double y;
};
int main(void) {
struct Point p;
p.x = 3.0;
p.y = 4.0;
printf("%.1f, %.1f\n", p.x, p.y);
return 0;
}Put the struct definition above main so the compiler already knows the type when it reaches the function. You can read and write the fields from main.
The dot operator
p.x means “the x field of p”. The dot does not copy the struct. It selects one member. You can use a field anywhere you would use a variable of that field’s type: print it, add to it, pass it to a later function.
Example
#include <stdio.h>
struct Player {
char name[8];
int score;
};
int main(void) {
struct Player hero = {"Nia", 1200};
hero.score = hero.score + 50;
printf("%s has %d\n", hero.name, hero.score);
return 0;
}Compile this at /c/try. Change the starting score and run again. The name lives in achar array; a C string is not a separate type.
Mix types freely inside one struct: numbers, characters, arrays. Keep the fields related. A player record should not also store a random file path.
Assign one struct to another
Assignment copies every field. After b = a, the two variables are independent. Changingb.x leaves a.x alone.
Example
#include <stdio.h>
struct Point {
double x;
double y;
};
int main(void) {
struct Point a;
a.x = 2.0;
a.y = 5.0;
struct Point b = a;
b.x = 9.0;
printf("a: %.1f, %.1f\n", a.x, a.y);
printf("b: %.1f, %.1f\n", b.x, b.y);
return 0;
}You can also fill a struct with a brace list in declaration order:struct Point origin = {0.0, 0.0};. That is a copy of the values into a new object, not a live link to another point.
Many variables, one type
struct Point is a type you invented, the same way int is a type the language invented. You can declare as many struct Point variables as you need. You can put structs in arrays:struct Point corners[4]; is four points, each with an x and a y.
| Piece | Role |
|---|---|
struct Point { ... }; | Names the type and lists fields |
struct Point p; | Creates one object |
p.x | Reads or writes a field |
struct Point b = a; | Copies every field |
typedef waits
A later chapter shows typedef, which can turn struct Point into a shorter name. Until then, write struct at every declaration. If you catch yourself writing x1,y1, x2, y2, stop and make a Point.
The semicolon after the struct’s closing brace is part of the definition. Functions do not need that extra semicolon after their body. Structs do.
Next: name a small set of choices with an enum instead of magic numbers.
Worked examples
The short listings above are there so you can see the grammar. The programs here use the same statements on quantities that already have units: a speed, a pH, a count of bases. They are classroom numbers. Air resistance is ignored. g is 9.81 m/s² unless a line says otherwise.
Open them in the C editor at /c/try. Change one measurement and check whether the result still has the right unit.
Physics
A force with two components
A force in a plane needs Fx and Fy. The magnitude is the same Pythagoras as a displacement: √(Fx² + Fy²). 3 N east and 4 N north is 5 N, at arctan(4/3) from the x-axis.
struct keeps the two components under one name so you do not pass fx and fy as unrelated arguments and swap them by mistake.
|F| = √(Fx² + Fy²)
Example
#include <stdio.h>
#include <math.h>
int main(void) {
struct Force {
double fx;
double fy;
};
struct Force f = {3.0, 4.0};
double mag = sqrt(f.fx * f.fx + f.fy * f.fy);
printf("|F| = %.1f N\n", mag);
return 0;
}Biology
Temperature and pulse together
A nurse does not store a temperature in one notebook and a pulse in another without a name linking them. They belong to one person at one time.
Fields on a struct are that record. 36.8 °C and 72 bpm is an ordinary resting pair. Neither field means much if you lose the pairing.
Example
#include <stdio.h>
int main(void) {
struct Vitals {
double temp_c;
int bpm;
};
struct Vitals p = {36.8, 72};
printf("%.1f C, %d bpm\n", p.temp_c, p.bpm);
return 0;
}