Skip to content

A first C program

A C program is a list of statements that run one at a time, starting in main. A compiler turns the file into a machine program before it runs.

This topic

First, the picture

A program is a list of instructions. Watch the computer follow this one, a line at a time, and keep an eye on total.

Running a program line by line

A loop adds 1 to 5 into total

#include <stdio.h> int main(void){    int total = 0;    for (int i = 1; i <= 5; i++)        total = total + i;    printf("total = %d\n", total);    return 0;}

Output

The program starts in main. Its box total has no value yet: “?”.

0.00 / 16.40 s
Describe this picture

The 10 lines of sum.c with the line about to run marked, beside a picture of the program’s memory under the label “Stack”: one card titled main, holding one row of 8 small cells. i, an int of 4 cells at 0x7fe8, fills the left half of the row once the loop starts; total, an int at 0x7fec, fills the right half. Each box shows its type and name at the top left, its address at the top right, and its value in the middle, ”?” until a line writes one. Under the picture the program’s output appears once it prints, and under everything one sentence on the current step. The clip plays the program once, 15 steps in about 16 seconds: 1.6 seconds a line before and after the loop, 1 second a line inside it, and rests on the end. When a line writes a box, the old value fades out as the new one comes in, and the box is outlined. i’s box appears, showing ”?”, when the mark first reaches line 6, and disappears when the loop ends. The mark goes from line 7 back to line 6 five times; then it moves to line 8, and total = 15 appears under the picture. The transport plays and pauses, steps one line back or forward, and scrubs; a paused step is kept in the page address as line.step.

Reading the picture

If you have never written a loop in any language, go slowly here: pause the picture and step through it a line at a time with the transport. The picture shows every step, so you can check each sentence below against it.

The mark in the code sits on the line about to run. The picture of memory shows the state after every line before it. So when the mark is on line 7 for the first time, line 6 has run, and line 7 has not.

The picture holds the program’s two variables. A variable is a named box that holds one value, and total and i are the two boxes here. A box shows ”?” until a line puts a value in it. The small number in each box’s top right corner, such as 0x7fec, says where the box is in memory. Variables live in memory (1.2) is about those numbers, so you can leave them aside for now.

= stores a value

Line 7 reads total = total + i;. In maths that would be false for every i except 0. In C, = is not a statement that two things are equal. It is an instruction: work out the right side with the values the boxes hold now, then store the result in the box on the left.

The first time line 7 runs, total holds 0 and i holds 1. The right side is 0 + 1 = 1, and 1 goes into total. The old 0 is gone. Watch total’s box: it holds one number at a time, and it does not remember the earlier ones.

The mark goes round

Watch where the mark goes after line 7. It goes back up to line 6, not on to line 8. Line 6 is the loop’s header, and it runs before every turn of the loop, not only at the start. On the first visit it sets i to 1; on each later visit it adds 1 to i. Each time, it then checks that i is still at most 5.

So the mark visits line 7 five times, with i = 1, 2, 3, 4 and 5, and total becomes 1, 3, 6, 10 and 15. After the fifth turn, line 6 makes i 6, and the check 6 <= 5 fails. The mark jumps to line 8, and the program prints total = 15.

The box for i appears when the loop starts and disappears when it ends. i was made by the loop, and it belongs to the loop.

Key idea

= works out the right side, then stores the result in the box on the left. A box holds one value at a time.

The code and its cost

Here is what each part of sum.c does, line by line.

  • #include <stdio.h> (line 1) brings in the standard input and output functions, printf among them.
  • int main(void) (line 3) starts the function named main. Every C program begins running at the first line of main. The int in front says that main hands back a whole number when it ends, and (void) says that it takes nothing in.
  • The braces on lines 4 and 10 group the lines between them into the body of main.
  • Each instruction, called a statement, ends with a semicolon.
  • int total = 0; (line 5) makes a variable named total, of type int, and stores 0 in it. An int holds a whole number. In C a variable’s type is fixed: total is an int for as long as it exists.
  • printf("total = %d\n", total); (line 8) prints the text between the quotes. %d is replaced by the value of total, written as a whole number, and \n ends the line.
  • return 0; (line 9) ends main, and with it the program. The 0 tells the system that started the program that all went well.

The four parts of a for loop

Line 6, for (int i = 1; i <= 5; i++), packs four parts into one line:

PartCodeWhen it runs
startint i = 1once, before everything else
testi <= 5before every turn; when it is false, the loop ends
bodyline 7once per turn
stepi++after every turn, before the next test; it adds 1 to i

The order is start, test, body, step, test, body, step, and so on, until the test is false. Start, test and step are all on line 6, which is why the mark keeps coming back to it. Without braces, the body of a for is the one statement that follows it; with braces it is every statement between them, as in the while loop of the worked example.

What the loop costs

The cost of a loop is how many times its lines run. Here line 7 runs 5 times, i++ runs 5 times, and the test runs 6 times: five times true, and once false, which ends the loop. Change the 5 in the test to 1000, and line 7 runs 1000 times. Nothing else in the program changes.

Change the test to i < 5 instead, and the loop stops after the turn with i = 4. The program prints total = 10.

Compiling and running

The computer cannot run sum.c itself. A program called a compiler reads the file and writes a machine program, and it is that machine program that runs. This course uses the compiler gcc:

sum.c        the file you write
  │  gcc
  ▼
sum          the machine program
  │  ./sum
  ▼
total = 15   what it prints

In a terminal, in the folder that holds sum.c, these two commands build the program and run it:

gcc -std=c11 -Wall -Wextra -g sum.c -o sum
./sum

-std=c11 picks the version of C this course uses. -Wall and -Wextra ask gcc to warn about anything that looks like a mistake. -g keeps the line numbers inside the program, so that a debugger can step it line by line; that is how the picture at the top of the page was made. -o sum names the machine program sum, and ./sum runs it.

The same as other languages, and different

If you have written programs in another language, most of this will look familiar. C has if and while, the arithmetic + - * / %, and the comparisons < <= > >= == !=. Two equals signs, ==, test whether two values are equal; one, =, stores. Dividing two ints drops the remainder: 7 / 2 is 3, and 7 % 2 is the remainder, 1.

Two things are different from many languages. The program is compiled before it runs, and every variable has a fixed type.

Worked example

Here is a while loop. It runs its body as long as its test is true, checking the test before every turn. Take a sheet of paper, write n and f at the top, and trace these lines by hand before you read on.

int n = 4;
int f = 1;
while (n > 1) {
    f = f * n;
    n = n - 1;
}
printf("f = %d\n", f);

Each time the test n > 1 is checked, the boxes hold:

CheckBoxesTestWhat happens
1n = 4, f = 1truef becomes 1 × 4 = 4, then n becomes 3
2n = 3, f = 4truef becomes 4 × 3 = 12, then n becomes 2
3n = 2, f = 12truef becomes 12 × 2 = 24, then n becomes 1
4n = 1, f = 24falsethe loop ends

The test is checked four times and fails on the fourth. The program prints f = 24, which is 4 × 3 × 2. The order of the two lines in the body matters: f is multiplied by n before n goes down.

The replay below runs these lines inside main, as lines 5 to 11 of factorial.c. Step through it and compare it with your sheet.

Tracing a while loop

n counts down from 4 while f collects 4 × 3 × 2

#include <stdio.h> int main(void){    int n = 4;    int f = 1;    while (n > 1) {        f = f * n;        n = n - 1;    }    printf("f = %d\n", f);    return 0;}

Output

main has started. n and f have no values yet.

0.00 / 26.60 s
Describe this picture

The 13 lines of factorial.c with the line about to run marked, beside the card for main: one row of 8 cells, f, an int at 0x7fe8, in the left half and n, an int at 0x7fec, in the right half. Each box shows its type and name, its address and its value, ”?” until written. The replay runs one line every 1.9 seconds, 15 steps in about 27 seconds, and rests on the end. n takes 4 and f takes 1; then the mark goes round lines 7, 8 and 9 three times while f becomes 4, 12 and 24 and n becomes 3, 2 and 1. On the fourth visit to line 7 the test fails and the mark moves to line 11. The output, f = 24, appears under the picture when line 11 has run. The sentence under the picture says which check each visit to line 7 is. The transport plays and pauses, steps one line back or forward, and scrubs; a paused step is kept in the page address as while.step.

Reading a warning

Now a mistake. Delete , total from line 8 of sum.c, so that the line reads printf("total = %d\n");. The file is sum-missing-arg.c. Compile it with the same command, and gcc prints:

sum-missing-arg.c:8:22: warning: format ‘%d’ expects a matching ‘int’ argument [-Wformat=]

8:22 is line 8, column 22, where the d of %d is. The message says that %d asks for an int to print, and the line gives it none. The [-Wformat=] at the end names the check, one of those -Wall turns on.

A warning does not stop gcc: the program is built, and it runs. But %d prints whatever number happens to be where the missing value should be. On my machine two runs printed −1263705800 and −2112275528. Treat every warning as a mistake to fix.

Where it’s used

Operating systems. The core of most operating systems, the part that runs programs and talks to the hardware, is written mostly in C.

Firmware. The small computers inside cars, washing machines and thermostats run programs written mostly in C, compiled for each chip.

Audio and signal processing. Audio and signal-processing libraries are often written in C for speed. Many instruments on this site’s signal processing pages run a small C library, compiled to run in your browser, that holds the fast Fourier transform of The FFT, convolution and filters.

Other languages. The standard interpreter of Python, the program that runs Python code, is itself a C program, and so are the runtimes of many other languages.

Reference card

CodeMeaning
int main(void) { … return 0; }the program starts at main’s first line; return 0 ends it and reports success
int total = 0;makes an int box named total and stores 0 in it
total = total + i;works out the right side, then stores it in total; the old value is gone
for (start; test; step) bodystart once, then test, body, step, test, … until the test is false
while (test) { … }test, body, test, body, … until the test is false
if (test) statementruns the statement only when the test is true
printf("total = %d\n", total);prints the text, with total’s value in place of %d
gcc -std=c11 -Wall -Wextra -g sum.c -o sumcompiles sum.c into the program sum; ./sum runs it
costa loop’s body runs once per turn; its test runs once more, and that last check fails

Platform: C11, gcc 13 on x86-64 Linux. The addresses in the pictures are short stand-ins, by one rule for the whole course.

End of the lesson

Where to go next.

New lessons by email

Are you 13 or over?

Accounts and email updates are for people aged 13 or over. We keep only your answer, never your date of birth.

Phasorium

Account

Sign inWith Google, GitHub or your email

Subjects

Site

Look