Variables, Types and Operators

Learn the fundamentals of C++ programming: declaring variables, using built-in data types, and performing operations with operators

Ryan McCombe
Updated

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:

  • those who have completed our introductory course, but want a quick review
  • those who are already familiar with programming in another language, but are new to C++
  • those who have used C++ in the past, but would benefit from a refresher

It summarises several lessons from our introductory course. For more thorough explanations or additional context, consider completing Chapter 1 of the beginner course.

Intro to C++ Programming

Become a software engineer with C++. Starting from the basics, we guide you step by step along the way

Comments

In C++, single line comments start with // and comment blocks extend from /* to */

// This is a single-line comment

/*
This is a multiline
comment
*/

Variables and Types

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};

Operators and Expressions

Once they've been created, variables are updated using the assignment operator =:

int MyInteger{42};
MyInteger = 10;

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};

White Space

C++ is mostly insensitive to spaces, tabs and line breaks. These are collectively known as white space. We can generally add or remove white space from our code to lay it out in any way we prefer:

int SomeInt{5};
int AnotherInt { 5 };

bool SomeBool {
  false
};

bool AnotherBool
  { false };

int A{5}; int B{10}; int C{15};

Automatic Type Deduction

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.

Type Conversions

C++ performs implicit type conversion at compile time where possible:

// 2.5 (double) converted to 2.5f (float)
float MyFloat { 2.5 };

// 2.0 (double) converted to 2 (int)
int MyInteger { 2.0 };

// 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

int MyInt { static_cast<int>(2.5f) };
float MyFloat { static_cast<float>(MyInt) };

Narrowing Conversions

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.

Most notably, uniform initialization 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. Narrowing 3.14 to an integer means we'll be using the value 3. This will mean future calculations are less accurate, and we may not even notice.

The compiler allows narrowing casts at initialization if we use =, but not if we use { and }:

// 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

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

Integer Division (Quotient and Modulus)

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

Order of Operations

C++ operators are subject to an order of operations. When these are mathematical operations, the order is equivalent to what we expect from math. For example, multiplication happens before addition:

4 + 2 * 2; // = 4 + 4 = 8

Order of operations can be manipulated by introducing brackets:

(4 + 2) * 2;  // = 6 * 2 = 12

Integer and Floating Point Interaction

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

When a floating point number is directly converted to an integer, the floating point component is discarded

int a = 2.1; // 2
int b = 2.5; // 2
int c = 2.9; // 2

When initializing a variable, the expression is evaluated before considering what type our variable should eventually have:

float a{5 / 2}; // 2.0

Assignment using = is an operator too, and it is ordered after most other operators:

float a;
a = {5 / 2}; // 2.0

Increment and Decrement Operators

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

Compound Assignment

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

Floating Point Shorthand

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

Thousands Separator

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

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 operand
bool 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;

Combining Booleans

Booleans can be combined using the logical and operator, &&:

true && true; // true
true && false; // false

// Simplifies to false && true
2 > 5 && 5 > 2; // false

We also have the logical or operator ||:

true || true; // true
true || false; // true

// Simplifies to false || true
2 > 5 || 5 > 2; // true

Boolean Order of Operations

Similar to other operators, && and || are subject to an order of operations. We can introduce brackets to control this:

// Simplifies to true && false
MyBool = (true || false) && false; // false

// Simplifies to true || false
MyBool = true || (false && false); // true

Boolean Inversion

Boolean expressions can be inverted using the ! operator

!true; // false
!false; // true

// Simplifies to !(false)
!(5 < 2); // true

// Simplifies to !(false || true), which is !(true)
!(5 < 2 || 10 > 5); // false

Boolean Implicit Conversion

Many types, including numeric types like int and float can be implicitly cast to booleans. Numeric values that are equal to 0 are considered false, whilst any non-zero number is considered true. For example:

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

Summary

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:

  • C++ is a statically-typed language, meaning we must declare the type of a variable when we create it
  • The basic built-in types are bool, int, float, and double
  • We can initialize variables using braced initialization with the { and } syntax
  • The auto keyword can be used for type deduction, but should be used sparingly for clarity
  • C++ provides arithmetic, comparison, and logical operators that work as expected from other languages
  • Integer and floating-point division work differently - integer division returns the quotient, while floating-point division returns a precise result
  • We can use explicit casts like static_cast when we need to convert between types
Next Lesson
Lesson 3 of 129

Introduction to Functions

Learn the basics of writing and using functions in C++, including syntax, parameters, return types, and scope rules.

Questions & Answers

Answers are generated by AI models and may not have been reviewed. Be mindful when running any code on your device.

How does integer division work in C++?
Can you explain more about how integer division and the modulus operator work in C++, with some examples?
Implicit casts between booleans and numbers in C++
The lesson mentions that numeric types can be implicitly cast to booleans in C++, with 0 being false and anything else true. Can you clarify how that works with an example?
What is uniform initialization in C++?
The lesson recommends using uniform initialization with braces (like int x {5};) instead of the = operator. What advantages does this have?
When should I use auto in C++?
The auto keyword seems convenient, but the lesson says to use it sparingly. When is it appropriate to use auto in C++?
How does operator precedence work in C++?
Can you clarify the rules around operator precedence in C++? How can I control the order of operations?
Prefix vs postfix increment in C++
What's the difference between the prefix and postfix increment/decrement operators in C++? When should I use one over the other?
Floating point precision in C++
I've heard that floating point numbers can sometimes be imprecise in C++. Can you explain why this happens and how to handle it?
Or Ask your Own Question
Get an immediate answer to your specific question using our AI assistant