Why C, and What a Program Really Is
Structured and Object Oriented: Two Ways to Organise a Program
In this lesson
- Define structured programming in one sentence.
- Explain what object oriented programming adds, and what it costs.
- Say why this track teaches structured C before anything else.
Kenji wants to skip ahead to C++. His reasoning is that objects are modern and C is not, so why spend months on the old shape. Amara asks him to open any C++ class he likes and read one method, line by line.
He does. It is a sequence of steps, with an if in the middle and a loop at the end. Every object's method is still made of the three moves from lesson 1. Objects are how you file the code, not what the code is.
Both shapes are answers to one question, and that question is what this lesson is really about.
The organising question
Every large program faces the same problem. How do you keep fifty thousand lines from becoming an unreadable mess? Structured programming and object oriented programming are two answers.
Structured programming organises by action. You split the problem into functions, which are small named blocks that each do one job. Data is one thing. The functions that work on it are another thing. You pass the data to the functions.
Object oriented programming organises by thing. You split the problem into objects. Each object carries its own data plus the functions that work on that data, packed together in one capsule.
The three moves, again
Here is the definition, and it is smaller than you expect. Structured programming is building a program out of sequence, selection and repetition, with no jumping about.
That is not a slogan. Corrado Böhm and Giuseppe Jacopini proved in 1966 that those three structures are enough to express any program. Two years later Edsger Dijkstra published a short letter titled "Go To Statement Considered Harmful". His argument was that jumping freely with goto made programs impossible to reason about.
One habit comes with it: every block has one way in and one way out. You do not jump into the middle of a loop from outside. That single rule is most of what makes a program readable by a human six months later.
Note
C still has goto. It is used in real code, mostly in kernels, for one narrow job. It jumps to a cleanup block when something fails halfway through. That is a single forward jump to one exit, which keeps the one-way-out habit. You will meet it in Module 6.
One small example, told twice
Amara has a bank account with 500 taka in it. She deposits 300, then tries to take out 1000, which should fail. Here is that program in both shapes, with the same output.
#include <stdio.h>
/* Data is a plain bundle of fields. It knows nothing about behaviour. */
struct Account {
char owner[32];
long balance;
};
/* Behaviour lives outside, as functions that receive the data they need. */
void deposit(struct Account *a, long amount)
{
a->balance += amount;
}
int withdraw(struct Account *a, long amount)
{
if (amount > a->balance) {
return 0;
}
a->balance -= amount;
return 1;
}
void print_account(struct Account a)
{
printf("%s has %ld\n", a.owner, a.balance);
}
int main(void)
{
struct Account amara = {"Amara", 500};
deposit(&amara, 300);
print_account(amara);
if (withdraw(&amara, 1000) == 0) {
printf("not enough money\n");
}
print_account(amara);
return 0;
}
Amara has 800
not enough money
Amara has 800
Notice the separation. struct Account holds data and knows nothing about printing. print_account holds behaviour and is handed the data. Nothing in this program is hidden from anything else.
You are not learning C++ today. Read this for its shape, and compare the output.
#include <iostream>
#include <string>
// Data and behaviour live inside one capsule, and the data is hidden.
class Account {
private:
std::string owner;
long balance;
public:
Account(std::string name, long start) : owner(name), balance(start) {}
void deposit(long amount)
{
balance += amount;
}
bool withdraw(long amount)
{
if (amount > balance) {
return false;
}
balance -= amount;
return true;
}
void print() const
{
std::cout << owner << " has " << balance << "\n";
}
};
int main()
{
Account amara("Amara", 500);
amara.deposit(300);
amara.print();
if (!amara.withdraw(1000)) {
std::cout << "not enough money\n";
}
amara.print();
return 0;
}
Amara has 800
not enough money
Amara has 800
Same three lines out. Two real differences went in. The functions now live inside the class, so you write amara.deposit(300) instead of deposit(&amara, 300). And balance is private, so no code outside the class can change it by hand.
Now look at Kenji's discovery. Inside withdraw, the body is a selection followed by two steps in sequence. The three moves did not go anywhere.
The university now needs teachers as well as students. A teacher has a name and a salary, and no marks. In the structured shape you add a second bundle and a second function.
#include <stdio.h>
/* Two kinds of thing. Each gets its own bundle and its own function. */
struct Student {
char name[32];
int marks;
};
struct Teacher {
char name[32];
long salary;
};
void print_student(struct Student s)
{
printf("student %s scored %d\n", s.name, s.marks);
}
void print_teacher(struct Teacher t)
{
printf("teacher %s earns %ld\n", t.name, t.salary);
}
/* The three moves, inside one ordinary function. */
int count_passing(struct Student list[], int n, int pass_mark)
{
int passed = 0; /* sequence */
for (int i = 0; i < n; i++) { /* repetition */
if (list[i].marks >= pass_mark) { /* selection */
passed++;
}
}
return passed; /* sequence */
}
int main(void)
{
struct Student class_list[3] = {
{"Kenji", 91},
{"Bob", 38},
{"Zara", 77}
};
struct Teacher maria = {"Maria", 48000};
for (int i = 0; i < 3; i++) {
print_student(class_list[i]);
}
print_teacher(maria);
printf("%d of 3 passed\n", count_passing(class_list, 3, 40));
return 0;
}
student Kenji scored 91
student Bob scored 38
student Zara scored 77
teacher Maria earns 48000
2 of 3 passed
Two functions with almost the same name, and the caller has to pick the right one. With two kinds of thing this is fine. With twenty kinds, object oriented programming starts to earn its cost. An object can simply be asked to print itself.
Look at count_passing too. It is labelled with the three moves. It is also the exact shape of every loop you will write from Module 6 onward.
The comparison, without a verdict
| Structured (C) | Object oriented (C++, Java) | |
|---|---|---|
| Basic unit | The function | The class and its objects |
| Organised around | What the program does | What the program has |
| Data and behaviour | Kept separate | Packed together |
| Data access | Usually open to any function | Usually hidden, reached through methods |
| Approach | Top down: split a big problem into smaller functions | Bottom up: build objects, then combine them |
| How code is reused | Call the function again | Inheritance and composition |
| Best for | Systems code, drivers, contests, small and medium tools | Large applications with many kinds of thing that interact |
| Extra cost | Very low | Some, in memory and in indirection |
When object oriented programming wins, honestly
It wins when you have many kinds of thing that must be treated the same way. A drawing program with circles, squares and text can ask every shape to draw itself. There is no list of special cases.
It wins when hiding matters. If balance can only change through deposit and withdraw, then a rule like "never go below zero" has exactly one place to live.
It wins on large teams. A capsule with a small public surface is a contract, and contracts let people work without reading each other's insides.
And it costs something. An extra layer of indirection, and more ceremony for small jobs. In large systems, deep inheritance chains that are hard to follow. Neither shape is better. They solve problems of different sizes.
Why this track starts with structured C
Three reasons. First, the three moves are the foundation of both shapes. They are easier to see with nothing else in the way.
Second, in C you will think in functions, and functions are the unit of both languages. Third, structure does not require classes. The Linux kernel is around 30 million lines of structured C, and one of the best maintained codebases on earth.
What structure does require is habits. Small functions. Clear names. One job per function. Those are the skills of Modules 7 and 8, and they are the whole heart of this language.
Where this is used
- The Linux kernel. Structured C at the largest scale in the world. It keeps data in structs and behaviour in functions. It does use one object-like trick, a struct of function pointers. That is how one interface serves many devices.
- SQLite. Structured C, roughly 250,000 lines, with a small public interface. Everything else is kept private by convention rather than by the language. It is a good argument that discipline matters more than syntax.
- Your browser. Chromium and Firefox are largely C++, full of objects, because a browser has thousands of kinds of thing that interact. Underneath, they call C libraries such as zlib.
- Python. Both, at once. You can write plain functions all day, and every value you touch is an object. The interpreter running both is structured C.
Common mistakes
1. Thinking C cannot be organised because it has no classes.
There is no error message for this, only messy code. C organises with structs, functions and separate files. Module 15 shows the header and source split that large C projects use instead of classes.
2. Passing a struct by value when you meant to change it.
void deposit(struct Account a, long amount) {
a.balance += amount; /* changes a copy, not the caller's account */
}
The compiler is silent. The balance simply never changes, and beginners lose an hour to it. The fix is in Example 1: take a pointer, struct Account *a, and use a->balance. Module 11 explains why.
3. Believing object oriented code is automatically better organised.
A class with forty methods and twelve fields is not organised, it is a mess with a lid on. Both shapes need small pieces with one job each. The language does not supply that part.
4. Skipping to C++ before functions are comfortable.
This is Kenji's mistake. A C++ method is a function with extra rules about where it lives. If functions, scope and pointers are still shaky, classes add a second thing to be confused about.
On paper, write the one-sentence definition of structured programming, then list the three moves with one everyday example each.
Rules. No looking back at the lesson. Your sentence must contain all three move names and the phrase "one way in and one way out".
Check yourself. Read your sentence to somebody and ask them to name the three moves back to you. If they cannot, your sentence is doing too much work.
Take Example 1 and add a fourth function, transfer, that moves money from one account to another.
Rules. It takes two accounts and an amount. It must refuse if the sender does not have enough. It must not duplicate the rule inside withdraw; call withdraw and deposit instead.
Check yourself. Move 200 from Amara to Zara, then try to move 5000. The totals of the two accounts must add up to the same number before and after the failed transfer.
Imagine the university in Example 3 grows to ten kinds of person, each needing its own print. Write, in plain English, what goes wrong in the structured shape.
Rules. Two paragraphs. The first names the exact problem, in terms of function names and the caller's job. The second proposes a repair that stays inside C, and admits what the repair still cannot do.
Check yourself. A strong answer arrives at something like the brain teaser's struct Shape. If it does, you have just rediscovered how the Linux kernel handles devices.
Common doubts
Is structured programming worse than object oriented programming?
No, and the question usually hides a different one: which fits this problem? Drivers, contest solutions and small tools are almost always structured. Large applications with many kinds of thing are usually object oriented.
Can you write object oriented code in C?
You can get close, using structs with function pointers, which is the brain teaser above. The Linux kernel does exactly this. What C will not give you is the language enforcing the hiding for you.
Should I learn C++ after this track?
If you are heading for contests, yes, and it is the next track in this series. The C you learn here transfers almost completely. Do the transfer after functions and pointers feel ordinary.
Is
gotoactually banned?No, and it appears in the Linux kernel thousands of times. The rule is not "never", it is "one way in, one way out". A forward jump to a single cleanup block keeps that rule; a jump backwards into a loop breaks it.
Why does this lesson show C++ at all if the track is about C?
Because you will hear both words in every interview and every syllabus. Seeing the same program twice, with the same output, is faster than any definition.
Key takeaways
- Structured programming builds a program from sequence, selection and repetition.
- Böhm and Jacopini proved in 1966 that those three are enough for any program.
- Every block has one way in and one way out, which is what keeps code readable.
- Structured code organises by action; object oriented code organises by thing.
- Objects add hiding and shared treatment of many kinds of thing, at some cost.
- C thinks in functions, and functions are the unit of both shapes, so we start there.
That closes Part Zero. The module test is next. Then Module 1 puts you in front of real C. You get its symbols, the complete ASCII table, and your first program taken apart line by line.
Keyboard: পরের lesson এ j, আগেরটায় k, editor খুলতে r।