Lecture 0: Introduction to C
Prerequisites: Basic computer literacy (file management, using a text editor, navigating a terminal).
1. Overview
- This chapter addresses the fundamental question of what a C programme is, how it is structured, and how one transforms source code into an executable programme.
- Upon completion, you will be able to write, compile, and run simple C programmes that perform basic input and output operations using
printfandscanf. - This chapter lays the groundwork for the entire module; all subsequent chapters (variables, conditions, loops, arrays, functions, bit processing, pointers, and files) build upon the concepts introduced here.
2. Learning Outcomes
Upon completing this chapter, you should be able to:
- Explain the Input–Process–Output (IPO) model and describe how a computer executes a programme.
- Articulate the historical significance of C and justify why it remains relevant for systems-level programming.
- Identify the principal components of a C programme: preprocessor directives, the
mainfunction, statements, and comments. - Write, compile, and execute a simple C programme using GCC on a Unix-like system.
- Use
printfto display formatted output andscanfto read user input from the console.
3. Key Terms
| Term (EN) | 中文 | Definition / Notes |
|---|---|---|
| IPO (Input–Process–Output) | 输入–处理–输出模型 | A conceptual model describing how a computer system receives data, manipulates it according to programmed instructions, and produces results. |
| Compiler | 编译器 | A tool (e.g., GCC) that translates human-readable C source code into machine code that the CPU can execute directly. |
| Preprocessor directive | 预处理器指令 | An instruction beginning with # (e.g., #include) that is processed before compilation proper; it typically inserts header file contents into the source. |
| Header file | 头文件 | A file (e.g., stdio.h) containing declarations of library functions; included via #include so the compiler knows how to handle calls such as printf. |
main function | 主函数 | The designated entry point of every C programme; execution begins at the first statement inside main. |
printf | 格式化输出函数 | A standard library function declared in <stdio.h> used to write formatted text to standard output (the console). |
scanf | 格式化输入函数 | A standard library function declared in <stdio.h> used to read formatted input from standard input (the keyboard). |
| Format specifier | 格式说明符 | A placeholder within a format string (e.g., %d for integers, %f for floating-point numbers, %s for strings) that indicates the type of data to be printed or read. |
| Source file | 源文件 | A plain-text file with a .c extension containing C source code. |
| Executable | 可执行文件 | The binary file produced by the compiler, which can be run directly by the operating system. |
4. Core Concepts
4.1 The Input–Process–Output Model
Every computer programme, regardless of its complexity, can be understood through the IPO model. Input refers to data provided to the system—typically via a keyboard, mouse, file, or network connection. Process denotes the set of instructions (the programme) that manipulate and transform that input data. Output is the result produced by the programme, whether displayed on screen, written to a file, or sent over a network.
In concrete terms, when you run a C programme that asks for your age:
- Input — the user types a number on the keyboard.
- Process — the programme stores that number in a variable and formats a response string.
- Output — the programme prints the formatted message to the console.
This model informs how we design programmes. Every programme you write in this module will follow this pattern, and recognising the three phases helps you decompose problems systematically.
Minimal example
File: p00_ipo.c
Build: gcc p00_ipo.c -o p00_ipo
Run: ./p00_ipo
#include <stdio.h>
int main() {
int number; /* will hold the input */
printf("Enter a number: "); /* prompt (output) */
scanf("%d", &number); /* input */
printf("Double: %d\n", number * 2); /* process + output */
return 0;
}
What you should see: The programme prompts for a number, then prints its double (e.g., entering 5 yields Double: 10).
Takeaway: Even the simplest interactive programme exhibits all three phases of the IPO model.
4.2 Why C? Historical Significance and Modern Relevance
C was developed by Dennis Ritchie at Bell Labs in the early 1970s and was used to re-implement the Unix operating system. Since then, it has profoundly influenced virtually every major programming language that followed, including C++, Java, C#, and even Python (whose reference interpreter, CPython, is itself written in C).
There are several compelling reasons to study C today:
- Foundational influence — The syntax and semantics of C pervade modern languages. Learning C equips you with transferable concepts (variables, loops, functions, pointers) that apply broadly.
- Hardware proximity — C permits direct manipulation of memory addresses and hardware registers, which is essential for operating systems, embedded systems, and device drivers.
- Performance — C programmes are compiled to native machine code, yielding execution speeds that interpreted or bytecode-compiled languages rarely match.
- Ubiquity — The Linux kernel, most real-time operating systems, database engines (e.g., SQLite), and a vast body of embedded firmware are written in C.
One might reasonably ask: Why not begin with Python? Python is undeniably more approachable for a beginner, but it deliberately abstracts away memory management, type sizes, and compilation. By learning C first, you develop a mental model of what the machine is actually doing beneath the abstractions, which makes you a stronger programmer in any language.
Takeaway: C remains the lingua franca of systems programming and provides unparalleled insight into how computers operate.
4.3 Structure of a C Programme
A minimal C programme consists of three elements: one or more preprocessor directives, the main function, and statements within that function. Understanding this structure is essential before writing any code.
-
Preprocessor directives begin with
#and are handled before the compiler processes the rest of the source. The most common directive is#include <stdio.h>, which instructs the preprocessor to insert the contents of the standard I/O header file so that functions likeprintfandscanfare available. -
The
mainfunction is declared asint main(). The keywordintindicates thatmainreturns an integer value to the operating system; by convention, returning0signals successful execution. The body ofmainis enclosed in braces{ }. -
Statements are the individual instructions executed in sequence. Each statement ends with a semicolon (
;). Statements may include function calls (e.g.,printf(...);), variable declarations, assignments, or control-flow constructs (covered in later chapters).
Additionally, C supports two styles of comments:
- Block comments:
/* ... */— may span multiple lines. - Line comments:
// ...— extend to the end of the current line (available since C99).
Comments are stripped out during compilation and serve solely as documentation for the programmer.
Minimal example
File: p00_hello.c
Build: gcc p00_hello.c -o p00_hello
Run: ./p00_hello
/* Include the standard I/O library so that
* printf is available for use.
*/
#include <stdio.h>
/* The main function: entry point of the programme.
* It receives no arguments and returns an integer.
*/
int main() {
// Print a greeting to the console
printf("Hello, World!\n");
return 0; // indicate successful termination
}
What you should see: The text Hello, World! appears on the console, followed by a newline.
Takeaway: Every C programme you write will follow this skeleton — include headers, define main, write statements, and return 0.
4.4 Compiling and Running a C Programme
Unlike interpreted languages (e.g., Python), C source code must be compiled before it can be executed. The compiler translates your human-readable .c file into a binary executable that the CPU can run directly.
The standard workflow is as follows:
-
Write the source code in a plain-text editor (e.g., VS Code, Vim, Nano) and save it with a
.cextension. -
Compile the source using the GNU Compiler Collection (GCC):
gcc -o hello hello.cHere,
-o hellospecifies the name of the output executable. If compilation succeeds without errors, a file namedhellois created. -
Run the executable:
./helloOn Windows with MinGW, the executable would be
hello.exe.
If there are errors in your source code (e.g., a missing semicolon), the compiler will report them with line numbers and descriptions. You must fix all errors before a successful compilation is possible. It is advisable to compile frequently — after every few lines of new code — so that errors are caught early and are easier to locate.
A note on the compilation pipeline: Strictly speaking, gcc performs four phases: preprocessing (expanding #include and macros), compilation (translating C to assembly), assembly (translating assembly to object code), and linking (combining object files with library code to produce the final executable). For now, it suffices to treat these as a single step.
Takeaway: The edit–compile–run cycle is the fundamental workflow of C development.
4.5 Output with printf
The printf function (short for print formatted) writes text to the console. Its first argument is a format string — a sequence of characters that may include ordinary text and format specifiers (placeholders beginning with %). Subsequent arguments supply the values to be substituted for those placeholders.
Key format specifiers:
%d— print an integer in decimal notation.%f— print a floating-point number.%s— print a string.%c— print a single character.
The escape sequence \n within a string literal represents a newline character, causing the cursor to move to the beginning of the next line.
Minimal example
File: p00_printf.c
Build: gcc p00_printf.c -o p00_printf
Run: ./p00_printf
#include <stdio.h>
int main() {
printf("Welcome to C programming!\n");
return 0;
}
What you should see: The message Welcome to C programming! is displayed, followed by a newline.
Takeaway: printf is the primary mechanism for producing console output; its format string/specifier system gives you precise control over how data is displayed.
4.6 Input with scanf
The scanf function (short for scan formatted) reads data from standard input (typically the keyboard) and stores it in one or more variables. Like printf, it uses a format string containing specifiers to indicate the expected type of input.
There is one critical syntactic requirement: when passing a variable to scanf, you must prefix it with the address-of operator &. This is because scanf needs the memory address of the variable in order to store the value it reads. Omitting & is one of the most common beginner errors and typically causes a segmentation fault or unpredictable behaviour.
Minimal example
File: p00_scanf.c
Build: gcc p00_scanf.c -o p00_scanf
Run: ./p00_scanf
#include <stdio.h>
int main() {
int age;
printf("Enter your age: ");
scanf("%d", &age); /* & is essential here */
printf("You are %d years old.\n", age);
return 0;
}
What you should see: The programme prompts Enter your age: , waits for the user to type an integer and press Enter, then prints (e.g.) You are 21 years old.
Takeaway: scanf with & is the standard mechanism for reading user input; always ensure the format specifier matches the variable type.
4.7 C as a High-Level Language and What Lies Beneath
C is classified as a high-level language because it abstracts away the details of individual machine instruction sets, allowing programmers to write portable code. However, compared with languages such as Python or Java, C sits closer to the hardware: it exposes memory addresses (via pointers, covered in Lecture 7) and provides minimal automatic resource management.
The journey from source code to execution passes through several layers:
- High-level language — the C code you write.
- Compiler — translates C into assembly language.
- Assembler — converts assembly into machine code (object files).
- Linker — combines object files and libraries into an executable.
- Machine code — binary instructions executed directly by the CPU.
Understanding this stack, even at a superficial level, demystifies what happens when you type gcc and helps you reason about performance, debugging, and platform differences.
Takeaway: C occupies a unique position — high-level enough for productivity, yet low-level enough to give direct control over hardware resources.
5. Worked Examples
Example 1: Displaying a Fixed Message
Problem: Write a programme that uses printf to display the exact message Welcome to C programming! on the console. The programme should use only printf and produce no other output.
Steps:
- Include the
<stdio.h>header to gain access toprintf. - Define the
mainfunction. - Call
printfwith the desired string, including\nfor a trailing newline. - Return
0to indicate successful termination.
Reference code
File: p00_ex1.c
Build: gcc p00_ex1.c -o p00_ex1
Run: ./p00_ex1
#include <stdio.h>
int main() {
printf("Welcome to C programming!\n");
return 0;
}
Output:
Welcome to C programming!
Why it works: The #include <stdio.h> directive makes printf available. The format string passed to printf contains only literal text and the escape sequence \n, so the function simply writes the message verbatim followed by a newline.
Example 2: Reading and Echoing an Integer
Problem: Write a programme that prompts the user to enter an integer, reads it with scanf, and then displays the message You entered: [number].
Steps:
- Declare an
intvariable to hold the input. - Print a prompt using
printf. - Read the integer with
scanf, using%dand the&operator. - Print the result using
printfwith a%dplaceholder.
Reference code
File: p00_ex2.c
Build: gcc p00_ex2.c -o p00_ex2
Run: ./p00_ex2
#include <stdio.h>
int main() {
int number;
printf("Enter an integer: ");
scanf("%d", &number);
printf("You entered: %d\n", number);
return 0;
}
Output:
Enter an integer: 42
You entered: 42
Why it works: scanf("%d", &number) reads an integer from standard input and stores it at the memory address of number. The subsequent printf call substitutes the value of number into the %d placeholder, producing the formatted output.
Example 3: Computing the Sum of Two Integers
Problem: Write a programme that reads two integers from the user and displays their sum.
Steps:
- Declare three
intvariables: two for the input values and one for the sum. - Prompt for and read each integer in turn.
- Compute the sum.
- Display the result.
Reference code
File: p00_ex3.c
Build: gcc p00_ex3.c -o p00_ex3
Run: ./p00_ex3
#include <stdio.h>
int main() {
int a, b, sum;
printf("Enter the first number: ");
scanf("%d", &a);
printf("Enter the second number: ");
scanf("%d", &b);
sum = a + b;
printf("The sum is: %d\n", sum);
return 0;
}
Output:
Enter the first number: 5
Enter the second number: 3
The sum is: 8
Why it works: Two calls to scanf read two integers into a and b respectively. The expression a + b is evaluated and its result stored in sum, which is then printed. This example demonstrates sequential input, simple arithmetic, and formatted output — the three phases of the IPO model in practice.
6. Common Mistakes
-
Missing
#include <stdio.h>: Without this directive, the compiler does not know the declarations ofprintfandscanf, resulting in implicit function declaration warnings or errors. Always include the appropriate headers. -
Forgetting the
&inscanf: Writingscanf("%d", number)instead ofscanf("%d", &number)is the single most common beginner error.scanfrequires a pointer (memory address); omitting&leads to undefined behaviour, which may manifest as a crash or silently corrupted data. -
Missing semicolons: Every statement in C must end with
;. Omitting one produces a compilation error, often reported on the following line, which can be confusing. If the compiler points to a line that appears correct, check the line immediately above for a missing semicolon. -
Mismatched format specifiers: Using
%fto print anint, or%dto print afloat, causes undefined behaviour. The format specifier must always correspond to the type of the argument. -
Forgetting
\nat the end ofprintf: While not an error per se, omitting the trailing newline causes the shell prompt to appear on the same line as your output, making the result difficult to read. Cultivate the habit of endingprintfstrings with\n.
7. Practice
7.1 Basic
- P1: Write a programme that prints
Welcome to C programming!exactly as shown. Acceptance: The compiled programme produces the single line of output above and nothing else.
7.2 Required
-
P2: Write a programme that reads a single integer from the user and prints
You entered: [number]. Input/Output: Prompt withEnter an integer:, then output the entered value. Acceptance: Matches the sample output format exactly (see Example 2). -
P3: Write a programme that prompts the user for their age and their favourite number, then prints:
Your age is: [age]Your favourite number is: [favourite_number]Input/Output: Two separate prompts, two lines of output. Acceptance: Entering
18and42produces the output shown above. -
P4: Write a programme that reads two integers and prints their sum. Input/Output: Prompt for each number separately; output
The sum is: [result]. Acceptance: Entering5and3yieldsThe sum is: 8.
7.3 Optional
-
P5: Extend P4 to also display the difference, product, and quotient of the two numbers. Use integer division for the quotient (i.e.,
a / b). Consider what happens when the second number is zero and add a comment noting this edge case. -
P6: Write a programme that reads the radius of a circle (as an integer) and prints its approximate area using the formula area = 3 × r × r (integer arithmetic only, no floating-point). Compare the result you get with the true value you would compute by hand.
8. Mini Task
Goal: Create a small personal-introduction programme that demonstrates all the core skills from this chapter: formatted output, user input, and basic arithmetic.
Deliverables:
README.md: Describe how to compile and run each source file; include sample terminal sessions showing expected output.src/p00_intro.c: A programme that asks the user for their name (as a string, using%s), their birth year (as an integer), computes their approximate age given the current year, and prints a summary such as:Hello, Alice! You are approximately 22 years old.src/p00_sum.c: The sum programme from P4.report.md: A brief reflection (5–10 sentences) describing any difficulties encountered during compilation or execution and how you resolved them.
9. Further Reading
- Kernighan, B. W. & Ritchie, D. M. (1988). The C Programming Language (2nd ed.). Prentice Hall — Chapter 1: "A Tutorial Introduction". This remains the definitive introduction to C by its creators.
- King, K. N. (2008). C Programming: A Modern Approach (2nd ed.). W. W. Norton — Chapter 2: "C Fundamentals". A more contemporary and pedagogically oriented treatment.
- GCC Documentation: https://gcc.gnu.org/onlinedocs/ — Reference for compiler flags, warnings, and platform-specific behaviour.
10. Appendix
A. Installing GCC
Linux (Debian/Ubuntu):
sudo apt update
sudo apt install build-essential
This installs GCC, make, and related tools.
macOS:
xcode-select --install
This installs Apple's Command Line Tools, which include a GCC-compatible compiler (clang).
Windows: Install MSYS2 and then run:
pacman -S mingw-w64-ucrt-x86_64-gcc
Alternatively, install WSL (Windows Subsystem for Linux) and follow the Linux instructions above. WSL is the recommended approach for this module.
B. Verifying Your Installation
Run the following command in a terminal:
gcc --version
You should see output indicating the GCC version number (e.g., gcc (Ubuntu 13.2.0-23ubuntu4) 13.2.0). If the command is not found, your installation was unsuccessful or the PATH environment variable is not configured correctly.
C. Recommended Editor Settings
Whichever editor you use, configure it to:
- Insert spaces rather than tabs (4 spaces per indentation level is conventional).
- Save files with UTF-8 encoding.
- Display line numbers (essential for locating compiler errors).