Before writing large systems, libraries, or high-performance applications, it is critical to understand what the smallest valid program looks like, why it works, and how execution begins.
C and C++ share a common heritage, but they differ in philosophy, abstraction level, and tooling.
In this article, we start from the absolute minimum in each language, then progressively explain why each construct exists, when you should use it, and how C and C++ diverge and overlap.
The Minimal C Program — Where Everything Begins
C is a procedural, low-level language designed to give the programmer precise control over memory, execution flow, and hardware interaction.
Because of this, C defines a very strict and explicit program structure.
At its core, every valid C program must contain exactly one entry point: main().
// hello.c
#include <stdio.h>
int main(int argc, char **argv) {
printf("Hello, World!\n");
return 0;
}
This small program contains every essential building block of C:
- preprocessing
- program entry
- function calls
- return values
Understanding each part explains how C programs start, execute, and terminate.
Comments in C — Explaining Intent, Not Behavior
Before understanding execution, we must understand how humans communicate intent inside code.
Single-Line Comments
Introduced officially in C99, single-line comments use //:
printf("Hello"); // prints Hello
When to use:
- Inline explanations
- Clarifying non-obvious logic
Why they matter:
Comments do not affect the compiler, but they dramatically affect maintainability.
Multi-line comments
Multi-line comments use / / and can span multiple lines:
/*
This comment spans
multiple lines
*/
When to use:
- File headers
- License blocks
- Long explanations
Preprocessor Directives — Preparing Code Before Compilation
Before the compiler even sees your code, the preprocessor runs first.
#include <stdio.h>
This directive literally copies the contents of stdio.h into your source file before compilation.
Why this is necessary:
- C has no built-in I/O
printf()is declared instdio.h- Without it, the compiler cannot type-check the function call
This explains why missing headers often cause compilation errors.
The `main()` Function — The Program Entry Point
Execution in C always begins with main():
int main(int argc, char **argv) { ... }
Breaking it down:
intargc(argument count)argv(argument vector)return 0;
Indicates the exit status returned to the operating system
Number of command-line arguments
Array of argument strings
Signals successful execution
In C, **every statement must end with a semicolon**.
This is not stylistic—it is part of the grammar.
Compiling and Running a C Program
Save the file as hello.c and compile on Linux:
$ gcc hello.c
$ ./a.out
Hello, World!
Understanding gcc vs g++
This distinction is critical when transitioning between C and C++.
- GCC (uppercase)
- gcc (lowercase)
- g++
GNU Compiler Collection (supports many languages)
GNU C Compiler
GNU C++ Compiler
Key differences:
gcc- Compiles
.cas C - Compiles
.cppas C++ g++- Compiles both
.cand.cppas C++ - Automatically links the C++ standard library
Example:
$ g++ hello.c -o output
$ ./a.out
Hello, World!
The Minimal C++ Program — C Evolved
C++ builds directly on C but introduces abstraction, safety mechanisms, and higher-level constructs.
A minimal C++ program looks familiar:
// hello.cpp
#include <iostream>
using namespace std;
int main(int argc, char** argv) {
cout << "Hello, World!\n";
return 0;
}
Although syntactically similar, important conceptual differences exist.
C++ Headers - Modernized and Namespaced
#include <iostream>
Unlike C, C++ headers do not use .h.
Examples:
iostreamstringvector
Why:
C++ organizes its standard library inside namespaces, improving scalability and safety.
Namespaces — Avoiding Global Name Collisions
using namespace std;
C++ introduces namespaces to avoid symbol conflicts.
Most standard library features—including cout—live inside the std namespace.
Without the using statement, you must write:
std::cout << "Hello, World!\n";
When to avoid using namespace std;:
- Headers
- Large projects
- Libraries
Output in C++ — Streams Instead of Format Strings
Instead of printf, C++ commonly uses the stream-based cout:
std::cout << "Hello, World!\n";
Here, the << operator is overloaded to send data into the output stream.
Even so, you can still use printf in C++, since C is part of C++.
Example using printf in C++:
#include <cstdio>
int main(int argc, char** argv) {
printf("Hello, World!\n");
return 0;
}
C Headers in C++ — Two Styles
C library headers in C++ use a prefix c and no .h:
| C Header | C++ Equivalent |
|---|---|
| stdio.h | cstdio |
| math.h | cmath |
| string.h | cstring |
Namespace Behavior
Functions from C headers do not require the std:: prefix when using their .h forms:
#include <stdio.h> // no namespace
printf("Works\n");
But when using the C++ <cxxx> headers, functions live inside the std namespace:
#include <cstdio> // inside std::
std::printf("Works\n");
Compiling and Running (C++)
$ g++ hello.cpp
$ ./a.out
Hello, World!
You can even write pure C code in a .cpp file and compile it, because C is fully supported inside C++.
Using C Inside C++ — Practical Integration
One of the advantages of C++ is that it includes the entire C language. This means you can write pure C code inside a .cpp file, call C standard library functions, and even integrate external C modules seamlessly. In this section, we explore the different ways to use C inside C++.
Linking External C Code — `extern "C"`
C++ performs name mangling; C does not.
// mylib.c
int add(int a, int b) {
return a + b;
}
// main.cpp
extern "C" {
int add(int a, int b);
}
#include <iostream>
int main() {
std::cout << add(2, 3);
}
Without extern "C", the C++ compiler changes the function names internally, causing linker errors.
Program Style — Shared Syntax, Different Culture
C and C++ share:
- semicolons
- braces
- whitespace rules
Whitespace
int main(int argc,char**argv){printf("Hello\n");return 0;}
Valid—but unreadable.
Brace Styles
K&R Style:
int main() {
return 0;
}
Allman Style:
int main()
{
return 0;
}
Indented Braces:
int main()
{
return 0;
}
There is no correct style—only consistent ones.
The classic K&R style, used in _The C Programming Language_, remains widely preferred.
Final Summary — C vs C++ at the Foundation Level
| Feature | C | C++ |
|---|---|---|
| Entry point | main() | main() |
| Output | printf | cout / printf |
| Headers | .h | no .h |
| Namespaces | ❌ | ✔ |
| OOP | ❌ | ✔ |
| Compatibility | Base | Superset |
C teaches you how programs work.
C++ teaches you how systems scale.
Understanding both—starting from the minimal program—is the foundation for embedded systems, operating systems, compilers, and high-performance software.