C Part I · Module 1 · Understanding C and How Programs Work
Your First C Program
Three chapters have talked about C. This one puts a complete program in front of you. It does not begin with Hello World, and that is deliberate: printing a message requires six unfamiliar things at once, and using six to teach one is how beginners end up copying code they cannot account for. Instead we start from the smallest program C allows — four lines, no library, nothing to take on trust — and add exactly one idea at a time until it prints something and reports a result. Every piece you meet is either explained here or openly marked as provisional, with the chapter that makes it precise named. By the end you will be able to point at any character in a small C program and say what it is doing there.
Foundation14 min readCPart IFundamentalsFirst Program
Part I · Module 1 · Chapter 1.4 · Your First C Program
1. Why Not Hello World First
Almost every C book opens with a program that prints Hello, world!. It is a fine program. It is a poor first program, for a reason worth naming.
To account for every part of it you need to know what including a file does, what that particular file contains, what calling a library function means, what text in quotation marks is, what a backslash followed by n means, and what main is. That is six unfamiliar ideas, and the thing they collectively achieve is printing one line.
So we will get there in four small stages instead. Each stage adds one idea, and after each one you could say what changed and why.
2. The Smallest Complete Program
This is a complete, valid C program. It compiles, it runs, and it is finished:
int main(void)
{
return 0;
}It produces no output. That is not a limitation to apologise for — it is the point. There is nothing here except the parts a program cannot do without, which makes it possible to account for all of them.
main
A program needs a place to begin. For an ordinary program — one you start yourself, on a computer running an operating system — C fixes that place's name: main. When your program starts running, main is where your code begins.
That is the full extent of what you need now. Chapter 1.7 examines what happens before main begins and what "starts running" actually involves — because, as it turns out, main is not the first thing that runs on the machine. Part II eventually meets software with no operating system beneath it, which can begin somewhere else entirely; it will say so when it does.
The braces
The { and } mark where main's body begins and ends. Everything between them is what main does, in order.
Braces group statements together throughout C, and the pairing is exact: every { has a matching }. This is the structure Chapter 1.1 mentioned when it said C's shape comes from braces and semicolons rather than from layout on the page.
void
void inside the parentheses says: main takes nothing. You are not handing it any information.
A program can be given information when it starts, and Chapter 12.6 covers that. Writing void is how you say you are not using it — which is what you want while learning, because it removes a question you have no use for yet.
int and return 0
These two go together.
The int in front of main says that main produces a whole number when it finishes. The return 0; is where it does so: it ends main and hands back the value 0.
The obvious question is who receives that number. The answer is the subject of Chapter 1.7, so here is the honest short version: whatever started your program can look at that number, and by long-standing convention 0 means "finished normally". A non-zero value means something went wrong. You will see this for yourself in stage 4.
int is also your first encounter with a type — Chapter 1.2 described a type as saying what kind of value you are dealing with. Module 2 is where types are properly taught. For now: int means a whole number.
The semicolon
The ; ends the statement — one step for the program to carry out. In C a statement is not ended by reaching the end of a line; it is ended by a semicolon. That is why the layout on the page is free, and it is also why a missing semicolon is one of the most common first errors. You will meet that error deliberately in Chapter 1.5.
3. Stage 2 — Making It Print Something
A program that produces nothing is hard to learn from, because you cannot see it working. So now we add output, and this is where the pieces from §1 arrive — one at a time, with a job.
#include <stdio.h>
int main(void)
{
printf("Hello, world!\n");
return 0;
}Compiled and run, this produces:
Hello, world!Four things are new. Take them in order.
printf is not a language feature. This is the first genuinely surprising thing about C, and it matters. Printing is not built into the language the way return is. printf is a function, and it lives in the collection of ready-made functions Chapter 1.2 mentioned — the standard library, which comes with your implementation. The specification describes the language and that library separately, which is why printf is every bit as standard as return while not being part of the language itself. You are not using a C keyword here; you are calling code somebody else wrote.
printf(...) is a call. The parentheses after the name mean "run this, with what is inside the parentheses". Module 5 teaches what a function is properly; what you need here is that the name identifies work to be done and the parentheses hand it what it needs.
"Hello, world!" is text. The quotation marks are not part of the message — they mark where the text begins and ends, exactly as the braces mark where main's body begins and ends. The text itself is Hello, world!. Module 8 covers what C is really doing with text; for now, quotation marks delimit it.
\n means a new line. This is one character's worth of instruction written with two characters, because there is no way to type a newline inside quotation marks. The backslash says "the next character is not literal" and n says "newline". Without it, the next thing printed would continue on the same line — which you will see in stage 3.
#include <stdio.h> is why printf works. Before your code can call printf, the compiler has to be told that printf exists and what it expects. That information lives in a file called stdio.h, and #include brings it in.
The compiler is genuinely strict about this. Chapter 1.3 explained that the specification decides what is correct C, not your compiler's willingness to guess — and a call to a function the compiler has never been told about is exactly the kind of thing it must complain about. Chapter 1.5 shows that complaint; Chapter 1.6 shows what #include physically does to your file, which is more literal than most beginners expect.
4. Stage 3 — Two Statements, and Why Order Is Visible
One statement cannot show you order. Two can.
#include <stdio.h>
int main(void)
{
printf("first\n");
printf("second\n");
return 0;
}Output:
first
secondNothing surprising — and that is worth stating explicitly, because it is a genuine property of C rather than an accident. Statements inside main are carried out in the order they are written, one finishing before the next begins. The first printf completes, then the second runs, then return 0 ends main.
Now remove one \n and watch what it was doing:
#include <stdio.h>
int main(void)
{
printf("first");
printf("second\n");
return 0;
}Output:
firstsecondThe two pieces of text ran together. Nothing moved to a new line because nothing asked to. This is the clearest way to see that \n is not decoration and not automatic: printing does exactly what you asked and nothing more.
5. Stage 4 — return 0 Is Not Decoration
Stage 1 claimed that the value main returns is a report, and that 0 means "finished normally". Here is the proof, which costs one character.
int main(void)
{
return 3;
}This program produces no output, exactly like stage 1. Run from a command line, though, the two are not the same: whatever started the program can ask what it reported, and this one reports 3 rather than 0.
That is the whole mechanism. The number is small, it is the only thing your program hands back through this route, and by convention 0 means success while anything else means a particular kind of failure that the program chooses.
You will see how to read the number yourself in Chapter 1.5, and Chapter 1.7 explains who is asking. Chapter 12.7 covers the conventions properly. The reason it appears now, in the first program, is so that return 0 never becomes a line you type without meaning: it is your program's report, and reporting success when something failed is a real bug.
6. Putting the Four Stages Side by Side
| Stage | What was added | What it made visible |
|---|---|---|
| 1 | int main(void), braces, return 0; | The minimum a C program needs to exist |
| 2 | #include <stdio.h>, printf, text, \n | That output comes from a library function, not from the language |
| 3 | A second statement | That statements run in written order, and \n is not automatic |
| 4 | A different return value | That return reports a result to whatever started the program |
Read downward, that is the whole of stage 2's Hello World — but now with each part accounted for rather than accepted.
7. What Is Still Provisional
This matters more than it might seem, so it gets its own short section. Three of the explanations above are deliberately incomplete, and you should know which:
mainis where your code begins, but not where the machine begins. Chapter 1.7.#includebrings in a description, but how it does that is more literal than "brings in" suggests. Chapter 1.6.intmeans a whole number, which is true and is a small fraction of what a type is. Module 2.
Nothing above is false. Each is the part of the truth that is useful now. When the fuller model arrives it will extend these, not replace them — and if a curriculum ever asks you to unlearn something it taught you, that is a failure of the curriculum, not a stage of learning.
8. What You Should Be Able to Say Now
- A C program begins, as far as your code is concerned, at
main. - Braces enclose the statements
maincarries out; a semicolon ends a statement, not the end of a line. voidinmain(void)says the program is not taking any information when it starts.intbeforemainandreturn 0inside it are a pair:mainreports a whole number, and0conventionally means it finished normally.- Printing is not a language feature.
printfis a function that comes with the implementation, and#include <stdio.h>is what tells the compiler about it. \nasks for a newline; without it, output continues on the same line.- Statements inside
mainrun in the order written.
9. Exercise
Exercise 1 — account for every character. Write out the stage 2 program and, for each of these, say in one short phrase what it is doing there: #include, <stdio.h>, int, main, (void), {, printf, ", \n, ;, return, 0, }.
Exercise 2 — predict the output. Without running it, write down exactly what this prints, including where the lines break:
#include <stdio.h>
int main(void)
{
printf("a");
printf("b\n");
printf("c\n");
return 0;
}Exercise 3 — classify the pieces. Of main, return, int, void, and printf — which are part of the C language itself, and which is not? Say how you can tell from the stage 1 and stage 2 programs alone.
Exercise 4 — find the wrong claim. A colleague writes: "#include <stdio.h> copies the printf code into my program." One word of that is wrong in a way that matters. Which part is wrong, and what does the file actually provide?
Exercise 5 — reason about a change you cannot yet run. A program's main ends with return 1; instead of return 0;, and produces identical output. Describe something that could behave differently as a result, and say which chapter will let you check it.
10. Summary
- The smallest complete C program is four lines with no library and nothing to take on trust; every part of it can be accounted for immediately.
mainis where your code begins, braces enclose what it does, and a semicolon — not a line break — ends a statement.intandreturn 0are a pair.mainreports a whole number when it finishes, and0conventionally means it finished normally. That report is real, not ceremonial.- Printing is not part of the language.
printfcomes with the implementation, and#include <stdio.h>is what lets the compiler check your call to it. - Output does exactly what you asked. No newline without
\n, no spacing you did not write. - Statements run in the order written, each finishing before the next begins.
You can now read a small C program. What you cannot yet do is turn one into something that runs — every output in this chapter was shown to you rather than produced by you. The next chapter fixes that: one command to compile, one to run, and a close look at what the compiler says when you get it wrong.
Standards & specifications
- Governing standard
- ISO/IEC 9899 (the C language standard)(opens ISO/IEC (JTC 1/SC 22/WG 14) in a new tab)
Defines the C language itself — the type system, expression semantics, object model, storage duration and the behaviour categories a conforming implementation must honour. It is a FAMILY of editions (C89/C90, C99, C11, C17, C23) and this curriculum names the edition wherever a claim depends on one. It does not define any foreign-function interface to a hardware description language, and it does not define platform behaviour: what a memory-mapped access does on real silicon is the implementation's and the device's contract, not this standard's. Working drafts published by WG14 are freely available and are what most engineers read day to day; a draft is not the published standard.
This page also covers RTL structure, verification approach and debugging technique. Those are engineering practice built on the standard, not requirements the standard itself imposes.
Where this fits
Part of the C Programming curriculum.
