Values and Types

In module 1 every value was typed straight into a call: circle(260, 170, 15, "green");. This lesson shows how a program works a value out, gives it a name, and changes it. It also shows why C++ wants to know what kind of value each name holds.

C++ as a calculator

A program can do arithmetic. Write the sum where a value would go, and the result is used.

#include <iostream>

int main() {
    std::cout << 2 + 3;
    std::cout << "\n";
    std::cout << 10 - 4 * 2;
    std::cout << "\n";
    std::cout << (10 - 4) * 2;
    std::cout << "\n";
}
5
2
12

2 + 3 is an expression: something the computer works out to get one value. + adds, - subtracts and * multiplies. The expression is worked out first, and then its value is printed. The output is 5, not 2 + 3.

There are no quotes around 2 + 3. Quotes would make it text, and text is printed exactly as it is written.

Look at the second and third lines of output. The order follows the rules you know from school.

A variable is a type, a name and a value

A variable is a named place that holds one value. This statement makes one.

int side = 120;
Part What it is
int the type: what kind of value the variable holds. int means a whole number
side the name
= "starts with this value"
120 the value

A statement that makes a variable is a declaration. After it, the name can be used wherever a value of that type could be written.

#include "scimigo.h"
using namespace scimigo;

int main() {
    int side = 120;
    canvas(600, 400);
    rectangle(100, 140, side, side, "teal");
    rectangle(380, 140, side, side, "teal");
    circle(300, 200, side - 90, "gold");
}

The value 120 is written once and used five times. Change the declaration to int side = 100; and both squares change together. The circle changes too, because its radius is worked out from side: a variable can be part of an expression.

Three rules about variables.

The compiler checks the type. This program asks for text to be put in an int.

#include <iostream>

int main() {
    int age = "twenty";
    std::cout << age;
}

It does not compile. The message is like this one.

your_program.cpp:4:9: error: cannot initialize a variable of type 'int' with an lvalue of type 'const char[7]'

Most of the words are for later modules. Read the part you know: line 4, and "a variable of type 'int'" was given something that is not an int.

Printing values

std::cout prints the value of a variable in the same way as it prints text. One statement can also send several things, each after its own <<. They are printed in order, from left to right, with nothing added between them.

#include <iostream>

int main() {
    int score = 90;
    std::cout << "score" << "\n";
    std::cout << score << "\n";
    std::cout << "Score: " << score << " out of " << 100 << "\n";
    std::cout << "Twice the score: " << score * 2 << "\n";
}
score
90
Score: 90 out of 100
Twice the score: 180

Compare the first two lines. "score" in quotes is text: five letters. score without quotes is the name of the variable, so its value is printed.

In the third statement, the spaces around the numbers are there because they are inside the quotes: "Score: " ends with a space, and " out of " starts and ends with one. << never adds a space.

From now on a line is usually ended with << "\n" at the end of the statement.

A new value for an old name

A variable can be given a new value after it has been declared. This is an assignment.

#include <iostream>

int main() {
    int price = 20;
    int old_price = price;
    price = 25;
    std::cout << "Now: " << price << "\n";
    std::cout << "Before: " << old_price << "\n";
}
Now: 25
Before: 20

Read price = 25; as "store 25 in price". The old value, 20, is gone from price.

= does not mean "is equal to", as it does in mathematics. It is an instruction, carried out once, at the moment the statement runs. The right side is worked out, and the result is stored in the variable on the left.

That explains old_price. The statement int old_price = price; ran when price held 20, so 20 was copied into old_price. The two variables are separate places. When price changed later, old_price kept its own copy.

An assignment has no type in front of it. The type is written once, in the declaration. Writing int price = 25; a second time would be a second declaration of the same name, and the compiler refuses it.

Read, work out, store

The right side of an assignment may use the variable that is on the left.

#include <iostream>

int main() {
    int balance = 100;
    balance = balance - 30;
    balance = balance * 2;
    balance = balance + 1;
    std::cout << balance << "\n";
}
141

In mathematics, "balance = balance - 30" could never be true. In C++ it is three moves, always in this order.

  1. Read the value the variable holds now: 100.
  2. Work out the right side with that value: 100 - 30 is 70.
  3. Store the result in the variable: balance now holds 70.

Each statement starts from the value the one before it left behind. A table with one row for each statement shows this. Making such a table is called tracing a program by hand.

Statement Read Work out balance afterwards
int balance = 100; 100
balance = balance - 30; 100 100 - 30 70
balance = balance * 2; 70 70 * 2 140
balance = balance + 1; 140 140 + 1 141

Whole numbers and numbers with a fraction

An int holds a whole number and nothing else. For a number with a fractional part, such as 0.75, use the type double. The fraction is written after a point.

#include <iostream>

int main() {
    double litres = 0.75;
    int bottles = 3;
    double total = litres * bottles;
    std::cout << "Total: " << total << "\n";
    std::cout << "Four bottles: " << litres * 4 << "\n";

    int whole_litres = total;
    std::cout << "Whole litres: " << whole_litres << "\n";
}
Total: 2.25
Four bottles: 3
Whole litres: 2

Notice three things.

Choose int for things you count (bottles, people, pixels) and double for things you measure (litres, prices, averages).

std::cout prints at most six digits of a double. Module 3 shows how to choose the number of digits.

Dividing whole numbers

/ divides. With two whole numbers, the result is a whole number: the fraction is dropped. % gives what is left over, the remainder.

#include <iostream>

int main() {
    std::cout << 17 / 5 << "\n";
    std::cout << 17 % 5 << "\n";
    std::cout << 17.0 / 5 << "\n";
}
3
2
3.4

5 goes into 17 three times, with 2 left over. So 17 / 5 is 3 and 17 % 5 is 2. Again the fraction is cut, not rounded: 19 / 5 is 3 as well.

The third line is different because 17.0 is a double. One double in a division is enough: the other number is turned into a double, and the fraction is kept.

/ and % are worked out before + and -, as * is.

The two together split a quantity into larger and smaller units.

#include <iostream>

int main() {
    int days = 45;
    int weeks = days / 7;
    int days_left = days % 7;
    std::cout << days << " days is " << weeks << " weeks and " << days_left << " days\n";
}
45 days is 6 weeks and 3 days

% also tells odd from even: a number % 2 is 0 when the number is even and 1 when it is odd.

Two cautions.

Storing the result in a double does not bring the fraction back. The right side is worked out first, and only then stored.

#include <iostream>

int main() {
    int sweets = 17;
    int children = 5;

    double each = sweets / children;
    std::cout << each << "\n";

    double sweets_exact = sweets;
    double each_exact = sweets_exact / children;
    std::cout << each_exact << "\n";
}
3
3.4

sweets / children is an int divided by an int, so it is 3. Then 3 is stored in each. By the time the double is involved, the fraction is already gone. In the second pair of statements one side of the division is a double, so the answer is 3.4. With a number written in the program, a point does the same job: sweets / 5.0.

Do not divide a whole number by zero. There is no answer, and the program stops.

Text in a variable

Text has a type as well: std::string. A program that uses it has the line #include <string> at the top.

#include <iostream>
#include <string>

int main() {
    std::string city = "Paris";
    std::string country = "France";
    std::string place = city + ", " + country;
    std::cout << place << "\n";
    std::cout << city + country << "\n";
}
Paris, France
ParisFrance

Between pieces of text, + means join: the second text is put straight after the first. Nothing is added between them. The comma and the space in the first line of output are there because ", " was joined in.

Two limits on +.

A std::string variable can be used wherever a call expects text. Here the same variable is drawn and printed.

#include "scimigo.h"
#include <iostream>
#include <string>
using namespace scimigo;

int main() {
    std::string colour = "purple";
    std::string label = "This is " + colour;
    canvas(600, 400);
    circle(300, 170, 80, colour);
    text(210, 320, label, 28);
    std::cout << label << "\n";
}
This is purple

Values that must not change

Some values are fixed for the whole program: the number of days in a week, a rate of tax. Put the word const in front of the declaration, and the compiler will not let any later statement change the variable.

#include <iostream>

int main() {
    const double pi = 3.14159;
    double radius = 10;
    std::cout << "Distance round the circle: " << 2 * pi * radius << "\n";
}
Distance round the circle: 62.8318

A const variable is read like any other. It cannot be assigned to.

#include <iostream>

int main() {
    const double pi = 3.14159;
    pi = 3;
    std::cout << pi << "\n";
}

The compiler answers with a message like this one.

your_program.cpp:5:8: error: cannot assign to variable 'pi' with const-qualified type 'const double'

It names line 5, the assignment. The mistake is found before the program runs, which is the point of const. Without it, the program would run and print wrong answers, and you would have to search for the reason.

const goes in front of any type: const int days_in_week = 7;.

How big can an int get?

An int is stored in a fixed amount of memory, so it has a largest and a smallest value.

#include <iostream>

int main() {
    int largest = 2147483647;
    std::cout << largest << "\n";
}
2147483647

That is a little more than two billion. The smallest value is about minus two billion. If a calculation goes past either limit, the result is wrong, and there is no message of any kind. The numbers in this part of the course stay far below the limit. For now it is enough to know that the limit exists.

One more rule. C++ lets you declare a variable without a value.

int count;

count does not start at 0. It holds whatever happened to be in that part of memory, so a program that reads it can do something different each time it runs. Give every variable a value in its declaration.