Module I · Basics of C · Lecture 2
🎯 Why This Matters
Before you can write a single working C program, you need to understand the skeleton every C program is built on. Think of it like learning to write a formal letter — before worrying about what to say, you learn where the date goes, where the greeting goes, and where the signature goes. C programs follow the exact same idea: a fixed structure that every compiler expects, every single time.
Once you understand this skeleton, reading any C program — no matter how complex — becomes far less intimidating. Whether it’s a 10-line “Hello World” or a 10,000-line operating system kernel, you’ll simply be looking for the same familiar parts, arranged in the same familiar order. In fact, the Linux kernel, the Python interpreter, and even parts of your phone’s firmware are written in C — and every single one of those files begins with the same basic skeleton you’re about to learn.
🕰️ A Little Bit of Context: Why C Looks the Way It Does
C was designed in the early 1970s by Dennis Ritchie at Bell Labs, with one goal in mind: give programmers a language that is close to the hardware (fast, efficient, minimal) but still readable by humans. That design goal is exactly why C enforces such a rigid structure. The compiler doesn’t guess what you mean — it expects things to be declared, defined, and terminated in a very specific way. This might feel strict at first, but that strictness is what makes C predictable, fast, and still relevant more than 50 years later.
Once you internalize the structure, you’ll notice it in nearly every C-derived language too — C++, Java, C#, and even JavaScript borrow the same “curly-brace, semicolon-terminated” philosophy.
🏗️ The Blueprint Analogy
Imagine you’re constructing a house. Before any furniture goes in, you need:
- A foundation — the base everything else stands on
- A front door — a single, defined entry point
- The rooms — where the actual living happens
- A furniture list — what goes in each room, and what kind (a bed, a table, a shelf) before you actually place it
A C program works the same way:
- Header files are the foundation — they bring in tools you’ll need
- The
main()function is the front door — execution always enters here first - Declarations are the furniture list — naming what you’ll need and what type it is
- Statements inside
main()are the rooms — where the real work happens
💡 Key Idea: No matter how large or complex a C program is, execution always begins at
main(). Everything else exists to support what happens inside it.
📋 The Six Building Blocks of a C Program
Textbooks sometimes simplify this to “four parts,” but a genuinely complete C program can include up to six distinct sections. Not every program needs all six, but professional code almost always follows this order:
- Documentation / comments
- Header files (preprocessor directives)
- Global declarations
- The
main()function - Local declarations and statements (inside
main()or other functions) - User-defined functions
Let’s walk through each one in detail, with examples for each.
0️⃣ Documentation / Comments
Good C programs often begin with a short comment block explaining what the program does, who wrote it, and when. The compiler completely ignores comments — they exist purely for humans reading the code later.
/*
* Program: Age Calculator
* Author : Ajay Dabade
* Purpose: Demonstrates the basic structure of a C program
*/
C supports two comment styles:
| Style | Syntax | Use case |
|---|---|---|
| Single-line | // comment | Quick notes on one line |
| Multi-line | /* comment */ | Longer explanations, headers |
1️⃣ Header Files (Preprocessor Directives)
These lines always appear near the top of a program and begin with a # symbol. They tell the preprocessor — a step that runs before compilation — to include extra functionality, like importing a toolbox before you start building.
#include <stdio.h>
#include <math.h>
Here, stdio.h stands for “standard input-output header” — it gives you access to functions like printf() (to display output) and scanf() (to take input). math.h, similarly, unlocks mathematical functions like sqrt() and pow().
Think of header files like appliance manuals — you don’t need to know how a microwave’s circuitry works internally; you just need the manual that tells you which buttons do what. #include hands you that manual for a whole set of ready-made functions.
2️⃣ Global Declarations
Sometimes a variable needs to be accessible to every function in the program, not just one. These are declared outside of main(), at the top level of the file, and are called global variables.
#include <stdio.h>
int totalStudents = 0; // global declaration — visible everywhere below this line
int main() {
totalStudents = 30;
printf("Total: %d", totalStudents);
return 0;
}
⚠️ Heads-up: Global variables are convenient but should be used sparingly — overusing them makes programs harder to debug, since any function can silently change their value.
3️⃣ The main() Function
Every C program must have exactly one main() function. It’s the designated starting point — the compiler doesn’t go looking for code anywhere else to begin with, no matter how many other functions exist in the file.
int main() {
// your code goes here
return 0;
}
The curly braces { } mark where the function begins and ends — like the walls of a room. Everything the program actually does lives between them. The return 0; at the end tells the operating system that the program finished successfully — by convention, 0 means “no errors,” and any non-zero value signals that something went wrong.
4️⃣ Local Declarations
Before you can use a variable inside a function, you must tell the compiler it exists — what its name is and what kind of data it will hold. This is called declaration, and in C, it must happen before the variable is used anywhere.
int age; // stores whole numbers
float price; // stores decimal numbers
char grade; // stores a single character
This is like labeling storage boxes before you put anything inside them — the compiler needs to know the box’s size and type in advance, because int, float, and char each reserve a different amount of memory.
| Data type | Stores | Typical size | Example value |
|---|---|---|---|
int | Whole numbers | 4 bytes | 25 |
float | Decimal numbers | 4 bytes | 3.14 |
char | A single character | 1 byte | 'A' |
double | High-precision decimals | 8 bytes | 3.141592653589 |
5️⃣ Statements
These are the actual instructions — the “verbs” of your program. Each statement ends with a semicolon ;, which tells the compiler “this instruction is complete.” Statements can assign values, perform calculations, make decisions, or print output.
age = 20; // assignment statement
printf("Result: %d", age); // function-call statement
total = price * quantity; // expression statement
6️⃣ User-Defined Functions
As programs grow, you’ll start breaking work into smaller, reusable chunks called functions — instead of cramming everything into main(). A user-defined function is declared, defined, and then called from main().
#include <stdio.h>
int square(int n) { // user-defined function
return n * n;
}
int main() {
int result = square(5); // calling the function
printf("Square: %d", result);
return 0;
}
Think of main() as the manager of a small team, and user-defined functions as specialist employees. The manager doesn’t do every task personally — it delegates the squaring work to the square() function and simply uses the result.
💻 Putting It All Together
Here’s a more complete C program showing every section in its proper place:
/* Program: Simple Interest Calculator */ // 0. Documentation
#include <stdio.h> // 1. Header file
float rateOfInterest = 5.0; // 2. Global declaration
int main() { // 3. main() begins
int principal, time; // 4. Local declarations
float interest;
principal = 10000; // 5. Statements
time = 2;
interest = (principal * rateOfInterest * time) / 100;
printf("Simple Interest: %.2f", interest);
return 0;
} // main() ends
🔍 Trace it yourself: Cover the comments above and try to identify each of the six parts on your own before checking. This kind of code-tracing is exactly the skill this lesson builds toward.
🌍 A Real-World Way to Remember It: The Restaurant Analogy
Here’s an analogy that many beginners find sticks better than “blueprint”: think of a C program as a restaurant kitchen preparing one dish.
- Header files = the kitchen’s stocked pantry and equipment brought in before cooking starts (you don’t reinvent a whisk — you just bring one in)
- Global declarations = shared ingredients on the central counter, available to every chef in the kitchen
main()= the head chef, who owns the dish from start to finish and is the only one the restaurant manager talks to- Local declarations = the chef laying out exactly which pans and bowls they’ll personally need before starting
- Statements = the actual cooking steps — chop, stir, plate
- User-defined functions = specialist stations (a pastry chef, a grill chef) the head chef calls on for specific sub-tasks
Every dish that leaves the kitchen followed this same sequence — and every C program that compiles successfully followed the same sequence too.
🚫 Common Mistakes Beginners Make
Now that you know the structure, here are the most frequent structural errors new C programmers run into — and why the compiler rejects them.
| Mistake | Why it fails |
|---|---|
Forgetting #include <stdio.h> but still using printf() | The compiler has no idea what printf means without its header file |
| Using a variable before declaring it | C needs to know the variable’s type and reserve memory before it’s used |
| Missing a semicolon at the end of a statement | The compiler can’t tell where one instruction ends and the next begins |
Mismatched curly braces { } | The compiler can’t determine where main() (or any function) actually ends |
Defining two functions named main() | C requires exactly one entry point — having two creates ambiguity |
💡 Debugging tip: When your program refuses to compile, check these five mistakes first — in practice, they account for the vast majority of beginner errors.
🧩 Quick Reference Table
| Part | Purpose | Example |
|---|---|---|
| Comments | Explain code to humans; ignored by compiler | // notes |
| Header file | Brings in built-in functions | #include <stdio.h> |
| Global declaration | Variable visible to all functions | int total; |
main() | Program’s single entry point | int main() { } |
| Local declaration | Reserves memory for a variable | int age; |
| Statement | An instruction the program executes | printf("Hi"); |
| User-defined function | A reusable, named block of logic | int square(int n) { } |
🎓 Code-Tracing Exercises
Trace through each program below by hand — without running it — and answer the questions that follow.
Exercise 1: The Basics
#include <stdio.h>
int main() {
int x;
x = 5;
printf("Value: %d", x);
return 0;
}
- Which line is the header file?
- Which line declares a variable, and what type is it?
- Which line will actually produce visible output?
- What will the program print when it runs?
(Answer: it prints Value: 5.)
Exercise 2: Spot the Structural Error
This program has three structural mistakes. Can you find all of them before reading the answer?
int main() {
y = 10
printf("%d", y);
return 0
#include <stdio.h>
(Answer: (1) #include <stdio.h> appears after main() instead of before it; (2) y is used without being declared; (3) two missing semicolons — after y = 10 and after return 0.)
Exercise 3: Global vs. Local
#include <stdio.h>
int count = 100; // Line A
int main() {
int count = 5; // Line B
printf("%d", count);
return 0;
}
(Answer: it prints 5 — the local declaration on Line B “shadows” the global one on Line A inside main().)
❓ Frequently Asked Questions
Q: Can a C program run without a main() function?
No. The compiler will successfully compile files without main() only if they’re meant to be linked into a larger program (like a library); but to actually run as a standalone program, exactly one main() is required.
Q: Do header files always start with < and >?
Not always. Angle brackets (<stdio.h>) tell the compiler to look in the system’s standard library folders. Quotes ("myheader.h") tell it to look in your own project folder first — typically used for header files you write yourself.
Q: Why does return 0; matter if the program seems to work without it?
Some compilers are lenient and won’t complain, but return 0; is how your program formally reports success to the operating system. Skipping it is considered bad practice, and some compilers will flag it as a warning.
Q: What happens if I declare a variable but never use it?
The program will still compile and run fine — most compilers will just show a harmless warning about an “unused variable.” It’s not an error, just wasted memory and a sign the code could be cleaned up.
✅ Key Takeaways
- Every C program follows the same fixed structure: comments → header files → global declarations →
main()→ local declarations → statements → (optionally) user-defined functions. main()is always the starting point of execution, regardless of where other functions are defined in the file.- Declarations must come before a variable is used — the compiler needs to know its type and reserve memory in advance.
- Every statement ends with a semicolon — it’s how the compiler knows one instruction has finished and the next can begin.
- Header files aren’t optional decoration — leaving one out is one of the most common reasons a beginner’s program fails to compile.
🚀 Next up: Now that you can identify and construct every piece of a C program’s structure, we’ll look at how data actually moves through these statements using variables, data types, and operators in more depth.