This lesson is a quick introductory tour of variables and operators within C++. It is not intended for those who are entirely new to programming. Rather, the people who may find it useful include:
It summarises several lessons from our introductory course. For more thorough explanations or additional context, consider completing Chapter 1 of the beginner course.
In C++, single line comments start with //
and comment blocks extend from /*
to */
// This is a single-line comment
/*
This is a multiline
comment
*/
C++ is a strongly typed language, so we always declare the types of our variables. Statements end with a semicolon.
// A boolean - a true or false value
bool MyBoolean;
// An integer such as 42
int MyInteger;
// A floating point number such as 3.14
float MyFloat;
// "Double Precision" floating point numbers
// use extra memory to improve accuracy
double MyDouble;
Variables can be initialized at the same time they are declared. There are several ways of doing this, but we typically use braces {
and }
:
int MyInteger{42};
// Float literals have an f suffix
float MyFloat{5.2f};
double MyDouble{5.2};
bool MyBool{true};
Literals are code snippets that directly represent a value. Based on the formatting of the literal, the compiler can implicitly understand the type of the value.
For example:
true
is a bool
literal2
is an integer literal2.5f
is a float
literal2.5
is a double
literalOnce they’ve been created, variables are updated using the assignment operator =
:
int MyInteger{42};
MyInteger = 10;
Operators are instructions that perform defined actions on variables and values.
The objects they are operating on are known as operands.
A binary operator has two operands - a left and a right. The =
operator used above is an example of this, where the left operand was MyInteger
and the right was 10
Some operators only have a single operand - those are called unary operators.
Some symbols can be either a unary or binary operator, depending on how they are used. For example, the unary -
as in -x
indicates negation (returning the negative value of x
) whilst the binary -
as in x - y
indicates subtraction.
A sequence of operators and operands is called an expression. MyInteger = 10
was an expression. Expressions may return a result, which we can use as the operand of another operator, thereby creating a larger expression. This is what makes code like 1 + 2 + 3
work as we’d expect.
Literals, variables, and the result of expressions can be used interchangeably:
int MyInteger{2};
int AnotherInt{2 + 2};
int IntegerFromVariable{MyInteger};
int IntegerFromExpression{MyInteger + 1};
C++ is generally insensitive to white space. We can space our code as preferred:
int SomeInt{5};
int AnotherInt { 5 };
bool SomeBool {
false
};
bool AnotherBool
{ false };
int A{5}; int B{10}; int C{15};
When providing an initial value, we can ask the compiler to infer the type using the auto
 keyword.
Note that auto
is not dynamic typing. The type will be fixed once the variable is created:
// Creates a variable of type int
auto MyVariable { 10 };
This should be used sparingly, as visually concealing the types from our code can make it harder to understand and debug.
C++ performs implicit type conversion at compile time where possible:
// 2.5 (double) converted to 2.5f (float)
float MyFloat { 2.5 };
// 2.5 (double) converted to 2 (int)
int MyInteger { 2.5 };
// 2 (int) converted to 2.0 (double)
double MyDouble = MyInteger;
// 3 (int) converted to 3.0f (float)
float MyFloat = 1 + 2;
We can explicitly ask the compiler to do conversions using static_cast
. The syntax looks like this:
static_cast<type_to_cast_to>(value_to_cast)
For example:
static_cast<int>(2.5); // Returns 2
static_cast<float>(2); // Returns 2.0f
// It's reasonable to use auto here, as we already
// specify the type in the call to static cast
auto MyInt { static_cast<int>(2.5f) };
auto MyFloat { static_cast<float>(MyInt) };
There are other ways to initialize variables, including the =
operator, but uniform initialization using {
and }
is recommended. It includes some safeguards against potential human error.
For example, it will throw a compiler error if we attempt an implicit narrowing conversion which would cause data loss.
For example, if we try to store the floating point value 3.14
in an integer , that may be a mistake on our part. Rather than rounding the value to 3
, which we may not notice, the compiler instead throws an error if we use the { }
 syntax:
// Implicit narrowing conversion allowed
int MyNumber1 = 3.14;
// Implicit narrowing conversion disallowed
int MyNumber2{3.14};
// We make it explicit if this was intended
int MyNumber3{static_cast<int>(3.14)};
conversion from 'double' to 'int',
possible loss of data
Numbers support all the typical mathematical operators we’re familiar with from other programming languages. Below, we demonstrate this with integers, but the techniques work with any numeric type.
int x { 4 };
// Addition
x = x + 2; // x is now 6
// Subtraction
x = x - 2; // x is now 4
// Multiplication
x = x * 2; // x is now 8
// Division
x = x / 2; // x is now 4
When dividing integers, the result of 5
divided by 2
is considered to be 2, with 1Â remaining.
The /
operator returns the quotient (2
, in this example) whilst %
returns the modulus (1
, in this example)
// Integer division returns the quotient
5 / 2; // 2
// Modulus is available using % operator
5 % 2; // 1
C++ operators are subject to an order of operations. This can be manipulated by introducing brackets, (
and )
4 + 2 / 2; // 5 (4 + 1)
(4 + 2) / 2; // 3 (6 / 2)
Different numeric types generally interact in predictable ways. When either operand of division is a floating point number, the result will also be a floating point number
5 / 2.0; // 2.5
5.0 / 2; // 2.5
The increment and decrement operators (++
and --
) are available. They can come before the operand (as a prefix operator) or after the operand (as a postfix operator)
The prefix and postfix operators modify their operands in the same way. However, the prefix operators return the new value of the operand, whilst the postfix operator returns the previous value.
int x { 1 };
int y;
y = ++x; // both x and y are now 2
y = x++; // x is now 3, but y is still 2
int x { 1 };
int y;
y = --x; // both x and y are now 0
y = x--; // x is now -1, but y is still 0
A variable can be modified in place using the compound assignment operators, +=
, -=
. *=
and /=
.
These are shorthand ways of writing longer expressions. For example, x += 2
is equivalent to x = x + 2
More examples are below:
int x { 4 };
x += 5; // x is now 9
x -= 5; // x is now 4
x *= 2; // x is now 8
x /= 2; // x is now 4
When the decimal component of a floating point number is 0, it can be omitted
float MyFloat { 2.f }; // 2.0f
double MyDouble { 2. }; // 2.0
The '
character can be added to numbers for readability. Typically, this is used as a thousands separator for large numbers:
int ABigInteger { 1'000'000'000 };
float ABigFloat { 2'000'000'000.f };
Booleans in C++ have the bool
type, and their literal values are either true
or false
bool Bool1 { true };
bool Bool2 { false };
A boolean value in C++ can be generated in the same way as almost every other modern programming language. We have the 6 usual comparison operators:
==
returns true
if the two operands are equal!=
returns true
if the two operands are not equal>
returns true
if the left operand is larger than the right operand>=
returns true
if the left operand is larger than or equal to the right operand<
returns true
if the left operand is smaller than the right operand<=
returns true
if the left operand is smaller than or equal to the right operandbool MyBool { false };
// The equality operator: ==
MyBool = 5 == 5; // true
// The inequality operator: !=
MyBool = 5 != 5; // false
// The greater than operator: >
MyBool = 5 > 2; // true
MyBool = 5 > 5; // false
// The greater than or equal to operator: >=
MyBool = 5 >= 5; // true
// The less than operator: <
MyBool = 5 < 2; // false
MyBool = 5 < 5; // false
// The less than or equal to operator: <=
MyBool = 5 <= 5; // true;
Booleans can be combined using the logical and operator, &&
:
true && true; // true
true && false; // false
5 > 2 && 5 > 10; // false
We also have the logical or operator ||
:
true || true; // true
true || false; // true
5 > 2 || 10 > 5; // true
Similar to other operators, &&
and ||
are subject to an order of operations. We can introduce brackets to control this:
MyBool = (true && false) || true; // false
MyBool = true && (false || true); // true
Boolean expressions can be inverted using the !
 operator
!true; // false
!false; // true
!(5 < 2); // true
!(5 > 2 || 10 > 5); // false
Numeric types can be implicitly cast to booleans. 0
is falsey; anything else is truthy
A "falsey" object is something that can be converted to a boolean, and will have a value of false
A "truthy" object is something that can be converted to a boolean, and will have a value of true
bool MyBool { 0 }; // false
bool MyBool { 1 }; // true
Similarly, the opposite is true, although less useful. Boolean true is implicitly cast to numeric 1
, whilst false
is cast to 0
int MyInt { true }; // 1
float MyFloat { false }; // 0.f
In this lesson, we took a tour of the fundamental building blocks of C++: variables, primitive data types, and operators. We learned how to declare and initialize variables, work with the built-in types, and perform operations on them. Key takeaways:
bool
, int
, float
, and double
{
 and }
 syntaxauto
 keyword can be used for type deduction, but should be used sparingly for claritystatic_cast
 when we need to convert between typesLearn the fundamentals of C++ programming: declaring variables, using built-in data types, and performing operations with operators
Comprehensive course covering advanced concepts, and how to use them on large-scale projects.