Chapter 3
Variables, and the Types They Insist On
Giving values names, and saying what kind of thing they are.
The program in chapter 1 printed the same sentence every time you ran it. That’s fine for a greeting, and useless for almost everything else. Programs get interesting when they can hold on to something.
Giving a value a name
int score = 7;
Three parts, then the semicolon you’ve already been bitten by:
int— what kind of thing this is. A whole number.score— the name, which you chose.= 7— the value it starts out holding.
Now the name stands in for the value everywhere you use it:
#include <iostream>
int main() {
int score = 7;
std::cout << "Score: " << score << '\n';
}
Score: 7
Look closely at that cout line, because it has both kinds of thing on it.
"Score: " is in quotes, so it’s literal text and gets printed exactly. score
has no quotes, so it’s a name, and what gets printed is the value behind it.
Why C++ makes you say what kind
Some languages let you write score = 7 and work out the rest themselves. C++
wants to be told first, and the reason is worth understanding rather than just
tolerating.
Try lying to it:
int score = "seven";
wrongtype.cpp:4:9: error: cannot initialize a variable of type 'int'
with an lvalue of type 'const char[6]'
4 | int score = "seven";
| ^ ~~~~~~~
1 error generated.
Don’t worry about const char[6] — that’s the compiler’s name for a piece of
text, and chapter 24 explains why it’s spelled so strangely. What matters is
everything that didn’t happen. Your program never ran. Nothing half-worked,
nothing behaved oddly at 3am for a user in another country. The mistake was caught
while you were sitting right there.
That’s the deal C++ offers: tell me what kind of thing this is, and I’ll check your work before it ever runs.
Exercise 1 · Lie to the compiler
Type that line into a file and compile it. Read the message properly — file, line, column, and the two types it’s complaining about.
Then try double price = "free"; and bool ready = "yes";. Same complaint, new
words. You’re getting quick at these now.
The four you need today
| Type | Holds | Example |
|---|---|---|
int |
Whole numbers, positive or negative | int score = 7; |
double |
Numbers with a fractional part | double price = 2.5; |
bool |
true or false, and nothing else |
bool passed = true; |
std::string |
Text | std::string name = "Ada"; |
There are more — C++ has a whole cupboard of number types — but these four cover most of what you’ll write for a long time.
Two practical notes. std::string needs #include <string> at the top, alongside
<iostream>. And double is called that for historical reasons involving
“double precision”; chapter 6 explains why it occasionally gives you answers that
look wrong.
Changing it later
A variable varies. That’s the whole point of the name:
int score = 7;
score = 9;
The first line makes it and gives it a starting value. The second one replaces
that value. No int the second time — the type was settled when the variable was
created, and it can’t change.
Things that should never change
Some values shouldn’t move once set. A tax rate, a maximum, the number of cards in a deck. Say so:
const double tax_rate = 0.2;
Then try to change it, and the compiler stops you:
constchange.cpp:3:14: error: cannot assign to variable 'tax_rate' with
const-qualified type 'const double'
3 | tax_rate = 0.25;
| ~~~~~~~~ ^
constchange.cpp:2:18: note: variable 'tax_rate' declared const here
const is a promise you make to yourself and hand to the compiler for
enforcement. It costs one word, and it converts “I’m fairly sure nothing changes
this” into something checked. Use it whenever you can.
The value you never set
You’re allowed to make a variable without giving it a value:
int score;
std::cout << score << '\n';
Compile that and the compiler will warn you — -Wall earning its place again:
uninit.cpp:5:18: warning: variable 'score' is uninitialized when used here
[-Wuninitialized]
5 | std::cout << score << '\n';
| ^~~~~
But it’s a warning, not an error, so you still get a program. Run it and it prints something: maybe 0, maybe 32767, maybe a different number tomorrow. C++ doesn’t tidy the space before handing it to you, so you get whatever was lying around.
That’s the whole habit: give every variable a value when you make it. It costs nothing and removes an entire category of baffling bug. Chapter 31 has the proper name for what you’re avoiding, and it’s a good one.
What you’re allowed to call things
Names can use letters, digits and underscores, and can’t start with a digit. No
spaces, no hyphens. score, total_price and player2 are fine; total price
and 2nd_player are not.
Case matters: score and Score are two different variables, which is an
excellent way to confuse yourself at midnight.
Beyond the rules, use names that say what the thing is. total_price beats tp,
and it beats x by a mile. You are writing for the version of you that comes back
in a month having forgotten everything.
Check yourself
Project
A receipt
Roughly 30 minutes
Write a program that prints a receipt for a single item. It should hold, in properly named variables:
- the item’s name, as a
std::string - how many were bought, as an
int - the price of one, as a
double - a tax rate, as a
const double— it isn’t going to change while the program runs, so say so
Then work out the subtotal, the tax and the total, and print something like:
RECEIPT
-------------------------
Mechanical keyboard
2 x 49.5
Subtotal: 99
Tax: 19.8
Total: 118.8Rules: every variable gets a value on the line that creates it, and every
name says what it holds. No x, no t2.
Stretch: add a second item with its own name, quantity and price, and make the total cover both. You’ll notice you’re copying and pasting three variable declarations and changing the names. Hold that thought — it’s the itch that chapters 9 and 14 scratch.