Why C, and what makes it different
C is a compiled, general-purpose language designed in the early 1970s and still used wherever speed and direct control of hardware matter — operating systems, embedded devices, and the runtimes of newer languages including Python.
Two consequences follow, and both shape everything in these chapters. C is statically typed: every variable's type is declared before use and cannot change, so mistakes are caught by the compiler rather than at run time. And C is close to the machine: it does very little for you automatically, which makes it fast and makes certain mistakes possible that a language like Python would prevent.
| Part | Purpose |
|---|---|
| #include <stdio.h> | makes printf and scanf available |
| int main() | the entry point — execution begins here |
| { … } | braces group statements into a block |
| ; | ends every statement |
| /* … */ or // | comments, ignored by the compiler |
| return 0; | reports success to the operating system |
From source code to a running program
A C program passes through four stages before it runs, and knowing them explains where different errors come from.
The preprocessor handles the lines beginning with #: it pastes in the contents of included header files and substitutes any defined constants. The compiler then translates the resulting C into assembly, and reports any syntax or type errors. The assembler turns that into machine code, producing an object file. Finally the linker joins the object file to the library code — the actual implementation of printf — and produces the executable.
A linker error is not a compiler error
If you misspell a keyword, the compiler complains and names the line. If you call a function that was declared but never defined — or forget to link a library — the compilation succeeds and the linker fails with a message like "undefined reference", naming no line at all. Knowing which stage failed tells you where to look, and the exam asks for the distinction directly.
The three kinds of error
C distinguishes them sharply, and the difficulty of finding each is the opposite of what beginners expect.
| Error | When found | Example | How hard to find |
|---|---|---|---|
| Syntax | at compile time | a missing semicolon | easy — the compiler points at it |
| Runtime | while running | dividing by zero | moderate — the program crashes |
| Logical | never, by the machine | using + where * was meant | hardest — it runs and is wrong |
Why logical errors are the dangerous ones
A syntax error stops the program being built, so it cannot cause harm. A logical error produces a program that compiles cleanly, runs without complaint, and gives the wrong answer — which nobody may notice for months. This is why tracing a program by hand and testing with data whose answer you already know are worth the time they take.
Writing code somebody can read
C does not care about layout: the whole program could be written on one line. Everyone who reads it afterwards cares a great deal, and that includes you.
Indent the body of every block by a consistent amount. Give variables names that say what they hold — total_marks rather than t. Comment the reasons rather than the actions: /* only students who sat the paper */ is useful, /* add 1 to i */ is not. And keep each function short enough to see at once.
Identify the errors in this program and state the type of each. #include <stdio.h> / int main() { / int a = 5 / printf("%d", b); / return 0; }
- Line 3 has no semicolon after
int a = 5— a syntax error.Every statement must be terminated. The compiler will report this and stop. - Line 4 uses
b, which was never declared — also a syntax error in C.C requires every variable to be declared before use, so the compiler catches this rather than the program failing later. - Both are found at compile time, so the program never runs.That is what makes syntax errors the least dangerous kind.
- The fix: add the semicolon and declare
b, or printainstead.Which of the two was intended is a question the compiler cannot answer for you.
A missing semicolon and an undeclared variable — both syntax errors, caught at compile time.
Before you leave this chapter
- Every C program has one main(), and execution begins there.
- Statements end with a semicolon; braces group them into blocks.
- Preprocessor → compiler → assembler → linker. A linker error names no line.
- Syntax errors stop compilation; runtime errors crash; logical errors run and are wrong.
- Logical errors are the dangerous ones, because nothing complains.
The parts of a program, named
Exam questions frequently show a short program and ask you to identify its parts by name. The vocabulary is small and worth being exact about.
A keyword is a word reserved by the language — int, if, return, while — and cannot be used as a name. An identifier is a name you choose for a variable or function. A literal is a fixed value written directly in the code, such as 42 or "Hello". An expression produces a value; a statement performs an action and ends with a semicolon.
| Rule for identifiers | Example |
|---|---|
| May contain letters, digits and underscore | total_marks |
| Must not begin with a digit | 2marks is invalid |
| Must not be a keyword | int int; is invalid |
| Case sensitive | Total and total differ |
| No spaces or punctuation | total marks is invalid |
Why C is case sensitive and Pascal was not
C treats Total, total and TOTAL as three different identifiers. This is a deliberate choice, and it means a program can declare count and later use Count without any error — the compiler simply reports an undeclared identifier at a line where you are certain the variable exists. Consistent naming is not a style preference in C; it prevents a real class of bug.