Important takeaways

  • Programs keep track of data in memory using variables and constants
    • variables can change throughout a program; may be unknown until run time
    • constants remain unchanged throughout a program; must be known at compile time
  • Think of variables and constants as named buckets in memory
  • In C++, each bucket must be of a specific type, and only data of that type can be stored in the bucket; e.g., int buckets can only hold whole integers between -231 and 231
  • An example variable declaration and assignment is: int age = 100;
  • An example constant declaration is: const int PI = 3.14;
  • Literals are values of a particular type that are used directly in a program, not through a variable or constant; e.g., 100 and 3.14 in the above assignments

Contents

Types

When programming, we usually need to keep track of data throughout the life of the program. For example, if we are programming a calculator program, we need to keep track of the operator, the operands, and the result. Each piece of data can be classified as a particular type, such as a whole number (e.g., 10), a real number (e.g., 2.93), a character (e.g., 'h'), or a string of characters (e.g., "hello"). In this section we will discuss the specifics of the most basic and common types available in C++. In later chapters, we'll see how we can create our own custom types using C++ structs and classes.

\ref lists the most common C++ types we'll use, along with examples.

C++ types
TypeDescriptionExamples
intWhole integers, up to ±327675, 10, -2039
longWhole integers up to ±2147483647-5, 10000000
floatFloating point (decimals)4.5, 3, 9.139482
doubleLonger decimals39929391.9103
charSingle character (a whole integer between 0–255)'+', 'Z', 127
stringA string of characters"Hello there!"
boolBoolean (true or false)true, false, 1, 0

The key with types is to choose the one that best fits the data you want to store. For example, if you are trying to keep track of a person's age, then an int is the best fit, since you can reasonably expect the age won't go outside of the range and you don't need a decimal. If you need to keep track of a name, then you should use a string, since names are sequences of characters. An initial or individual symbol (like '*') is best represented using a char, though you could also use a string. Use a bool when you need to keep track of a binary state, e.g., whether a game is over or not.

(Back to top)

Variables

When we want to store data that we don't know at the beginning of our program (because we want to read it in from the user or base it on a computation), or if the data might change throughout the course of a program, we can store it in a variable. A variable stores values that can vary. The value of a variable can be set over and over again.

There are several parts to using variables: declaring, initializing, accessing, and reassigning. We talk about these below, as well as scope.

Declaring variables

In order to use a variable in C++, we must first declare it. A declaration is a line of code that tells the compiler that we want to set aside a box of memory of a certain type and identified by a name. It consists of the type followed by the name of our variable (the name is also called an identifier), and ends with a semi-colon (as do all statements in C++). This must be done before we can ever use a variable or assign a value to it. For example, to declare a variable to hold an age, we can do the following:

Here are a few more examples:

There are rules about identifiers, however. For instance, they may not start with any character other than a-z, A-Z, and _. In addition, no reserved C++ keywords can be used, which include the following:

alignas, alignof, and, and_eq, asm, auto, bitand, bitor, bool, break, case,
catch, char, char16_t, char32_t, class, compl, const, constexpr, const_cast,
continue, decltype, default, delete, do, double, dynamic_cast, else, enum,
explicit, export, extern, false, float, for, friend, goto, if, inline, int,
long, mutable, namespace, new, noexcept, not, not_eq, nullptr, operator, or,
or_eq, private, protected, public, register, reinterpret_cast, return, short,
signed, sizeof, static, static_assert, static_cast, struct, switch, template,
this, thread_local, throw, true, try, typedef, typeid, typename, union,
unsigned, using, virtual, void, volatile, wchar_t, while, xor, xor_eq

While the C++ compiler doesn't really care what you name your variables, you should. The style I recommend is to avoid all but the most common abbreviations and use camelCasing when your identifiers consist of multiple words. For example, if I have a variable to store my brother's age, I would name it: brothersAge, rather than broAge, brother_age, or, worst of all, ba. There are certain situations when a single letter identifier is okay, but in general, you should avoid it. Identifiers that are easy to read and understand improve code comprehension. That's good for you, for me, and for anyone else who ends up looking at your code.

Assigning values to variables

Once a variable has been declared (so the compiler knows about it), we can store data in the variable via an assignment. Assignments come in to flavors: the very first assignment to a variable is called an initialization (since we're setting the variable's initial value); any assignment thereafter is referred to as a reassignment.

In C++, we use the = sign to mean "gets", or "is assigned". The variable that is getting the value is on the left, and the value that is being gotten is on the right. For example, age = 5; will assign the value 5 to the variable age. We read this "age gets the value 5" or "age is set to 5". It is quite common to think of = the way it is used in math—it's different in programming! In programming, it's an assignment operator, not a test of equality. The thing on the left always gets the value of whatever is on the right.

Initialization can take place either at the same time a variable is declared or sometime after the declaration. For example, here's an example of separating the two steps:

And here's the version where they happen at the same time:

Here are the assignments for the variables we declared in the previous subsection:

The right hand side of an assignment can also be a variable or complex expression. For instance, if we have another variable, say, brothersAge, and I want to set age to the value stored in brothersAge, then I could do that with this assignment: age = brothersAge;. This assumes, of course, that both variables have been declared and that brothersAge has been initialized. E.g.,:

At the end, the value stored in age is 10 and the value stored in brothersAge is 11. Why? In memory, the assignment operator copies the value stored in the variable on the right at that point in the program and stores it in the variable on the left. They are not being linked—the data is being copied.

Expressions

Expressions are segments of code that can be evaluated by the computer and replaced with a resulting value. A variable by itself constitutes an expression. A literal (e.g., 10) is an expression, too. However, expressions can be longer and involve any number of operators and function calls. An example of a more complex expression would be a mathematical one, e.g.,:

Here we've initialized brothersAge to 11. We then assign brothersAge-1 to age, which is 10. So the final value of age is 10. For numerical types, like int, long, float, and double, we can use a series of operators between them: +, -, /, *.

Numerical-type variables can also use short cuts for reassigning their values, as shown in the table below:

Numerical expression operators
OperatorDescriptionExampleEquivalent to
+=Increments the variable on the left by the value on the rightage += 10;age = age + 10;
-=Decrements the variable on the left by the value on the rightage -= 10;age = age - 10;
*=Multiplies and updates the variable on the left by the value on the rightage *= 10;age = age * 10;
/=Divides and updates the variable on the left by the value on the rightage /= 10;age = age / 10;
++Increments the variable on the left by oneage++;age = age + 1;
--Decrements the variable on the left by oneage--;age = age - 1;

Whole number integers (e.g., of type int and long) can make use of the modulo operator, represented as %. Modulo yields the remainder after dividing the right operand by the left operand. E.g., 10 % 7 is 3, because 7 goes into 10 once, with a remainder of 3. So the assignment int age = 10 % 7; will assign 3 to the variable age.

Other types of variables can be used with operators, as well. For instance, if we have two strings, we can concatenate them (glue them together) as in the following program:

Here the variable messageFull is given the value "Hello there" as a result of the expression messageFirstHalf + messageSecondHalf. Here's another example that makes use of a string function length() (we'll actually call these "methods" later in the semester):

In this example, we first declare a string variable named name, then assign it the string literal "George Washington". On line 2, we declare an integer variable nameLength and set it to the number of characters contained in the value stored in name. Double quotes are not part of the string, so the length is 17.

Scope

Where variables are declared in a program also matters. Variables must be declared in the scope in which they are used. Until we learn about functions, main will be our primary scope. So, we should declare all the variables we need at the top of the main function:

What if we did the following?

The variable age has a global scope in this example because it can be accessed everywhere—in every single function in your code. Global scope should almost always be avoided with variables. There is no situation in this class where you should declare a variable in the global scope. The primary reason for this is that you have no control over what functions modify the value stored in global variables. There are better ways to pass values within your code. (In certain types of programming, such as for game development or graphical user interface development, global variables are considered okay and even sometimes required; we will not be doing any such development in this class.)

Two variables in the same scope cannot share the same name. If an identifier exists as a higher scope (e.g., in the global scope), then a variable of the same name may be declared in a lower scope (e.g., in main). When this happens, we say that the variable in the lower scope shadows the other identifier. Here's an example:

While we will shy away from global variables in this class, we will find that constructs such as loops also have a lower scope that the function in which they reside, causing shadowing issues.

(Back to top)

Constants

Variables are perfect when we have data that might vary during the lifetime of the program. Sometimes, however, we need a value that we know will never change during a program. For example, π (3.14...) or the minimum drinking age in the US. C++ gives us a special keyword to stick in front of our declaration to say "this value will never change": const. This is then followed by the type, the identifier, and the initialization. Unlike variables, constants must be initialized when they are declared and we can never reassign a value to a constant. Here's an example of declaring a constant for π and the minimum drinking age:

Notice that constants' names are all upper case, and spaces are represented as underscores. This is not a requirement of C++, but rather the convention we (and most other programmers) will use for constants in C++ (and many other languages). It makes it extremely easy to tell what values are constants later on in the program.

Also unlike variable, the most appropriate place for constants are in the global space. So add them to the header of your C++ programs. One of our reasons for not wanting variables to be global is that we lose control over what code can reassign values to global variables. However, since constants cannot be changed, we don't have that worry. Moreover, constants are always hard coded, whereas variables are usually read in from a user, file, or are the result of a calculation (our early examples are an exception to this generalization). Because constants are hard coded, having them at the top of the program makes them easy for a programmer to update as needed and recompile the program (e.g., if we needed more precision for PI, or if the minimum drinking age changed). Here's an example of a program with our constants declared:

(Back to top)

Literals vs. variables vs. constants

Now that you've learned about variables and constants, it's time to learn about some nomenclature that will make it easier for us to talk about them and the data we store in them.

A variable is a C++ entity that allows us to label a box of memory for storing data of a given type (like an int or string). The value stored in that box can change during the lifetime of a program.

A constant is like a variable, except that its value must be initialize when the constant is declared, and it can never change during the lifetime of a program.

A literal is a value of a given type. For example, a string literal consists of a pair of double quotes with text in between (like "Hello!"). Examples of int literals are: 5, 20093, and -13.

(Back to top)

A few things about string and char literals

We use strings a lot. Therefore, it's helpful for you to know a few extra things about them so that you'll get the most out of using them. As we saw in the examples above, string literals are surrounded by double quotes. like "Hello!". That's all well and good, but what happens when you want to use a double quote in the string itself? Or what if you want to represent some kind of whitespace character like a tab or new line? What other things can you embed in strings?

Here's a table with some character combinations and what they will do within a string. Notice that they all start with a backslash (\). Backslashes are used in C++ as what's called an escape character. A backslash tells the C++ compiler that the character (or characters) that follow should be treated specially and not taken at face value.

(Some) C++ escape sequences
Escape sequence Meaning
\" Embeds a double quote (as opposed to marking the end of a string literal).
\n Embeds a new line character (ASCII character 10).
\t Embeds a tab character (ASCII character 9).
\b Embeds a backspace character (ASCII character 8), which causes the cursor to back up one spot when printed to a CLI.
\a Causes an audible bell when printed to most CLIs.
\' Embeds a single (this is necessary only in char literals).

These can be used within char literals, as well. You can find out more about string and character literals on this Wikipedia page.

(Back to top)