Computer ScienceCore18 min read

Getting Started with C

The shape of a C program, and what happens between typing it and running it

This topic appears in:

01

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.

PartPurpose
#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
#include <stdio.h>/* bring in the standard I/O library */int main() {/* execution always begins here */printf("Hello\n");/* a statement, ended with a semicolon */return 0;/* 0 tells the OS the program succeeded */}every C program has exactly one main() function, and that is where it starts
02

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.

03

The three kinds of error

C distinguishes them sharply, and the difficulty of finding each is the opposite of what beginners expect.

ErrorWhen foundExampleHow hard to find
Syntaxat compile timea missing semicoloneasy — the compiler points at it
Runtimewhile runningdividing by zeromoderate — the program crashes
Logicalnever, by the machineusing + where * was meanthardest — 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.

04

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.

Worked example

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; }

  1. Line 3 has no semicolon after int a = 5 — a syntax error.Every statement must be terminated. The compiler will report this and stop.
  2. 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.
  3. Both are found at compile time, so the program never runs.That is what makes syntax errors the least dangerous kind.
  4. The fix: add the semicolon and declare b, or print a instead.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

  1. Every C program has one main(), and execution begins there.
  2. Statements end with a semicolon; braces group them into blocks.
  3. Preprocessor → compiler → assembler → linker. A linker error names no line.
  4. Syntax errors stop compilation; runtime errors crash; logical errors run and are wrong.
  5. Logical errors are the dangerous ones, because nothing complains.
05

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 identifiersExample
May contain letters, digits and underscoretotal_marks
Must not begin with a digit2marks is invalid
Must not be a keywordint int; is invalid
Case sensitiveTotal and total differ
No spaces or punctuationtotal 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.

Practice questions

6 questions · 20 marks · full working on every one

Try each one on paper first, then open the working. The marks are shown where they are actually awarded, because that is where they are actually lost.

Short questions

3 · 6 marks

Two marks each, in the style of the short-question section of the paper. Answer in two or three lines.

SQ1[2 marks]
What is the purpose of #include <stdio.h> and of main()?
Model answer

#include <stdio.h> instructs the preprocessor to insert the standard input/output header, making functions such as printf and scanf available. main() is the entry point — execution of every C program begins there.

Examiner tip. The word "entry point" is what the mark scheme wants for main. Saying it is "the main function" restates the name.

SQ2[2 marks]
Differentiate between a syntax error and a logical error.
Model answer

A syntax error breaks the rules of the language — a missing semicolon — and is found by the compiler, which refuses to build the program. A logical error is valid C that does the wrong thing, such as using + where * was intended: it compiles, runs, and produces an incorrect result that nothing reports.

Examiner tip. Say who finds each. The compiler finds one; only a human comparing output against expectation finds the other.

SQ3[2 marks]
What is the difference between a compiler error and a linker error?
Model answer

A compiler error is a fault in the source code itself — a syntax or type mistake — and is reported with a line number. A linker error occurs after successful compilation, when a function that was declared cannot be found, and names no line because the fault is a missing definition rather than bad code.

Examiner tip. The absence of a line number is the practical clue that you are looking at a linker error rather than a compiler one.

Solved numericals

2 · 8 marks

Full working, one step per line, with the marks shown where they are awarded.

N1[4 marks]
Describe the four stages between source code and an executable program.
Full working
  1. Preprocessor — processes # directives, inserting header files and substituting defined constants[1]
  2. Compiler — translates the C into assembly, reporting syntax and type errors[1]
  3. Assembler — converts assembly into machine code, producing an object file[1]
  4. Linker — combines the object file with library code to produce the final executable[1]

Preprocessing, compilation, assembly, linking.

Examiner tip. Four stages, four marks. Name each and say what it produces, in order.

N2[4 marks]
Write a C program that prints your name and the number 2026 on separate lines.
Full working
  1. #include <stdio.h>without it printf is undeclared[1]
  2. int main() { with a matching closing brace[1]
  3. Two printf statements, each ending in a semicolon, with \n for the line breaka single printf with two \n is equally acceptable[1]
  4. return 0; before the closing brace[1]

include, main, two printf calls with newlines, return 0.

Examiner tip. The \n is what produces "separate lines". Without it both outputs run together on one line and the question is not answered.

Long questions

1 · 6 marks

Theory and numerical together, as they appear in the long-question section.

LQ1[6 marks]
A student writes a C program that compiles without any error but prints an average of 0 for every set of marks entered.
  1. State the type of error and explain how you know.
  2. Give two plausible causes.
  3. Describe how you would locate the fault.
Mark scheme
  1. A logical error[1]
  2. It compiled successfully, so the syntax is valid, and it runs without crashing — so the fault is in what the program does rather than in how it is writtenthe reasoning is the mark[1]
  3. Cause: integer division — dividing two integers in C discards the fractional part, so 7/2 gives 3 and a total smaller than the count gives 0the classic C trap[1]
  4. Cause: the total is being reset inside the loop, or the division uses the wrong variableany second plausible cause[1]
  5. Trace the program by hand with two or three marks whose average you already know[1]
  6. Or add temporary printf statements showing the total and the count immediately before the division, to see which value is wrong[1]

(a) logical — it compiles and runs but is wrong (b) integer division, or the total reset inside the loop (c) hand trace with known data, or print the intermediate values

Examiner tip. Integer division is the single most likely cause of an average of 0 in C, and it is worth naming first: total / count with both declared as int gives a whole number every time.