CS 112
Introduction to Data Structures
Week 0
Intro to C++
Eric Araújo
Calvin University · Fall 2026
int main() {
return 0;
}
main().
#include <iostream>
using namespace std;
int main() {
cout << "Hello, World!" << endl;
return 0;
}
#include, namespace, and our main() function.
#include <iostream>
using namespace std;
int main() {
cout << "Hello, World!" << endl;
return 0;
}
#include <iostream>Pulls in the I/O library, C++'s version of import.
using namespace std;Lets you write cout instead of std::cout.
cout << … << endl;Prints to the terminal. << is the “injection” operator. endl ends the line and flushes the buffer, so the text appears immediately.
return 0;Tells the OS the program finished cleanly.
error: 'cout' was not declared in this scope
One file didn't make sense on its own: a typo, a missing #include, a type mismatch.
undefined reference to `helper()'
Every file compiled fine, but a function was declared and never defined.
.hDeclarations: what exists and how to call it. Shared by many
.cpp files, and never compiled on its own.
.cppOne .cpp after its headers have been pasted in. This is what the
compiler actually reads, and it becomes exactly one .o.
Live coding. What could possibly go wrong?
(the semicolon is always missing on line 12)
#include directives to pull in library declarations (C).
cout << sizeof(int); // 4: check any type yourself
cout << sizeof(double); // 8
cout << sizeof(grade); // 1: works on variables too
sizeof tells you the truth on yours.string keeps its characters on the heap, memory the program asks for while it runs. More on that in week 4.
x = 7
int x = 7;
main(). Watch what happens when we assign x = 3.14.
x = 3.14
x = 3.14;
x points at a new float object, and the int 7 is abandoned.int, so 3.14 is truncated to 3.
...
int count; // declared: NOT initialized
int total = 0; // declared and initialized
double pi = 3.14159;
char grade = 'A';
bool ready = true;
string name = "Ada";
cout << "count: " << count << endl; // ⚠️ undefined: could print anything
cout << "total: " << total << endl; // always 0
...
int x = 11;
x = "12";
x was declared as int.
Assigning a string literal to it is a type error; the compiler rejects it.
const
const int MAX_SIZE = 100;
const double PI = 3.14159265;
MAX_SIZE = 200; // ❌ compiler error: read-only!
const before the type to make a variable read-onlyALL_CAPS names for constantsconst liberally; it documents intent and catches bugs at compile time.
#include <iostream>
using namespace std;
int main() {
double value;
cout << "Enter a number: "; // output → terminal
cin >> value; // input ← terminal
cerr << "got " << value << endl; // error stream
cout << "You entered: " << value << endl;
return 0;
}
cout + <<: injectioncin + >>: extractioncin flows in, cout and cerr flow out.ifstream, and it is the next slide.
#include <iostream>
#include <fstream> // ifstream reads a file, ofstream writes one
#include <cmath> // sqrt
#include <cassert>
using namespace std;
int main() {
ifstream fin("numbers.txt"); // open the file, attach a stream to it
assert(fin.is_open()); // a missing file is not an error to ignore
double n; // ONE variable, reused for every number
while (fin >> n) { // read the next number; false when none left
cout << sqrt(n) << endl; // fin has already moved past that number
}
fin.close(); // hand the file back to the OS
return 0;
}
ifstream reads from a file exactly like cin reads from the terminal.fin >> n is false once the file runs out.
fin >> n Actually Doesfin is a read head parked in it. Every >> converts the next characters into a double and drags that head forward.<< runs the other way, and does not care where it is pointed: cout for the screen, an ofstream for a file.
int x = 33; // decimal (default)
int y = 0x21; // hex: 2×16 + 1 = 33
int z = 0b100001; // binary: 1×32 + 1 = 33
cout << x << " " << y << " " << z << endl;
// Output: 33 33 33
0x prefix → hexadecimal (base 16)0b prefix → binary (base 2)Prof. Rocky Chang, our department
Rocky, an Eridian, from Project Hail Mary
Three limbs down, two up: two hands of three fingers, so he counts in sixes.
Everything on the machine is bits. Hex is just a friendlier way to read them.
xkcd #99 · xkcd.com · CC BY-NC 2.5
Write the tests before the function; it forces you to think about what it should do:
assert(factorial(0) == 1);
assert(factorial(1) == 1);
assert(factorial(4) == 24);
assert(factorial(5) == 120);
unsigned factorial(unsigned n) {
unsigned result = 1;
for (unsigned i = 2; i <= n; ++i) {
result *= i;
}
return result;
}
int main() {
assert(factorial(0) == 1);
assert(factorial(1) == 1);
assert(factorial(4) == 24);
assert(factorial(5) == 120);
cout << "All tests passed!" << endl;
return 0;
}
Memory is a row of numbered boxes. A variable is one box.
int y = 77;
y is the box at 0x1004. The name is ours; the machine only knows the number.
& ("address-of") hands you the number of a box.
int y = 77;
int *x = &y; // x holds the address of y
x is an ordinary box too. What makes it a pointer is what it holds: an address.0x1004.
* means "go to that address".
int y = 77;
int *x = &y;
cout << x; // 0x1004: the address itself
cout << *x; // 77: follow the arrow
*x = 99; // write at the far end of the arrow
cout << y; // 99: y changed, without naming y
x and *x are different questions: which box versus what is in it.
int y = 77; // placed at address 0x1004
int *x = &y; // placed at address 0x1010
cout << x;
What is printed?
x holds the address of y. Printing x (no dereference) prints that address.
int y = 77;
int *x = &y;
cout << *y; // note: *y, not *x
What is printed?
y is an int, not a pointer. You can't dereference a non-pointer.
int y = 77;
int *x = &y;
cout << *x;
What is printed?
*x dereferences the pointer: follow the address stored in x to read the value there.
int y = 77;
int *x = &y;
*x = 78;
cout << *x;
What is printed?
*x = 78 writes 78 into the memory location that x points to. Dereferencing x now reads 78.
int y = 77;
int *x = &y;
*x = 78;
cout << y; // note: y, not *x
What is printed?
x points to y's memory location, so writing through *x changed y itself.
He did give him pointers. Three of them, and every one is a real address.
xkcd #138 · xkcd.com · CC BY-NC 2.5
Like Python lists, but fixed size and no bounds checking.
char letters[26]; // 26 chars, uninitialized
float scores[10] = { 0 }; // all 0.0
int vals[] = { 10, 9, 4, 2, 0 }; // size inferred: 5
0 to n−1
int arr[6] = { 1, 3, 5, 2, 77, -11 };
arr is a pointer to the first box, so arr[i] means "start at arr, step i ints along".
int arr[] = { 3, -11, 4, 12 };
int *ptr = &arr[2]; // ptr points at arr[2]
cout << *ptr << endl; // this box
cout << *(ptr + 1) << endl; // one int further along
cout << *(ptr - 1) << endl; // one int back
ptr + 1 does not add 1 to the address: it adds one int, so 4 bytes.arr[i] has been doing all along.
int arr[] = { 3, -11, 4, 12 };
int *ptr = &arr[2];
cout << *ptr;
What is printed?
ptr points to arr[2], which holds 4. Dereferencing it reads that value.
| Feature | Python | C++ |
|---|---|---|
| Variables | Reference to a typed object | Named memory location with explicit type |
| Type checking | Dynamic (runtime) | Static (compile time) |
| Function return type | Implied from return | Declared explicitly |
| 1D data structure | list | array or vector |
| Memory management | Automatic (garbage collected) | Mostly explicit |
| Entry point | First line executed | main() |
| Feature | Python | C++ |
|---|---|---|
| Interface / impl split | Not explicit | .h header + .cpp source |
| Parameter passing | Pass-by-value (objects by ref) | By-value, by-reference, by-const-ref |
| Access control | Mostly none | public / private |
| Constructors | Called explicitly | Explicit or implicit (scope entry) |
| Destructors | None (GC handles it) | Defined; called implicitly at scope exit |
| Generics | None | Templates, powerful but complex |
| Strings | Built-in | #include <string> |
main() and must be compiled before running
This deck stands on earlier CS112 materials by
Joel Adams and Victor Norman · adapted and extended by Eric Araújo