Navigation



2.1 — Basic addressing and variable declaration

Addressing memory

This lesson builds directly on the material in the section “A first look at variables“.

In the previous lesson on variables, we talked about the fact that variables are names for a piece of memory that can be used to store information. To recap briefly, computers have random access memory (RAM) that is available for program to use. When a variable is declared, a piece of that memory is set aside for that variable.

The smallest unit of memory is a binary digit (bit), which can hold a value of 0 or 1. You can think of a bit as being like a traditional light switch — either the light is off (0), or it is on (1). There is no in-between. If you were to look at a sequential piece of memory, all you would see is …011010100101010… or some combination thereof. Memory is organized into individual sections called addresses. Perhaps surprisingly, in modern computers, each bit does not get it’s own address. The smallest addressable unit of memory is a group of 8 bits known as a byte.

The following picture shows some sequential memory addresses, along with the corresponding byte of data:

Memory Addressing

Because all data on a computer is just a sequence of bits, we use a data type to tell us how to interpret the contents of memory in some meaningful way. You have already seen one example of a data type: the integer. When we declare a variable as an integer, we are telling the computer “the piece of memory that this variable addresses is going to be interpreted as a whole number”.

When you assign a value to a data type, the computer takes care of the details of encoding your value into the appropriate sequence of bits for that data type. When you ask for your value back, the program “reconstitutes” your number from the sequence of bits in memory.

There are many other data types in C++ besides the integer, most of which we will cover shortly. As shorthand, we typically refer to a variable’s “data type” as it’s “type”.

Declaring a variable

In the “basic C++” section, you already learned how to declare an integer variable:

int nVarName; // int is the type, nVarName is the name of the variable

To declare variables of other data types, the idea is exactly the same:

type varName; // type is the type (eg. int), varName is the name of the variable

In the following example, we declare 5 different variables of 5 different types.

bool bValue;
char chValue;
int nValue;
float fValue;
double dValue;

It’s that simple. (Well, almost — there are a few things you can’t name your variables, which we’ll talk about in the next section)

You can also assign values to your variables upon declaration. When we assign values to a variable using the assignment operator (equals sign), it’s called an explicit assignment:

int nValue = 5; // explicit assignment

You can also assign values to variables using an implicit assignment:

int nValue(5); // implicit assignment

Even though implicit assignments look a lot like function calls, the compiler keeps track of which names are variables and which are functions so that they can be resolved properly.

Declaring multiple variables

It is possible to declare multiple variables of the same type in one statement by separating the names with a comma. The following 2 snippets of code are effectively the same:

int nValue1, nValue2;
int nValue1;
int nValue2;

You can also assign them values on the declaration line:

int nValue1 = 5, nValue2 = 6;
int nValue3(7), nValue4(8);

Which is effectively the same as:

int nValue1 = 5;
int nValue2 = 6;
int nValue3 = 7;
int nValue4 = 8;

There are three mistakes that new programmers tend to make when declaring multiple variables in the same statement.

The first mistake is declaring each variable as int (or whatever type it is) in sequence. This is not a bad mistake because the compiler will complain and ask you to fix it.

int nValue1, int nValue2; // wrong (compiler error)

int nValue1, nValue2; // correct

The second error is to try to declare two variables of different types on the same line, which is not allowed. Variables of different types must be declared in separate statements. This is also not a bad mistake because the compiler will complain and ask you to fix it.

int nValue1, double dValue2; // wrong (compiler error)

int nValue1; double dValue2; // correct (but not recommended)

// correct and recommended (easier to read)
int nValue1;
double dValue2;

The last mistake is the dangerous case. In this case, the programmer mistakenly tries to initialize both variables by using one assignment statement:

int nValue1, nValue2 = 5; // wrong (nValue1 is uninitialized!)

int nValue1 = 5, nValue2 = 5; // correct

In the top statement, the nValue1 variable will be left uninitialized, and the compiler will NOT complain. This is a great way to have your program intermittently crash and produce sporadic results.

The best way to remember that this is wrong is consider the case of implicit initialization:

int nValue1, nValue2(5);

This makes it seem a little more clear that the value 5 is only being assigned to nValue2. The explicit assignment case is no different.

Where to declare variables

Older C compilers forced users to declare all of the variables in a function at the top of the function:

int main()
{
    // all variable up top
    int x;
    int y;

    // then code
    using namespace std;
    cout << "Enter a number: ";
    cin >> x;

    cout << "Enter another number: ";
    cin >> y;

    cout << "The sum is: " << x + y << endl;
    return 0;
}

This style is now obsolete. C++ compilers do not require all variables to be declared at the top of a function. The proper C++ style is to declare variables when and where they are needed:

int main()
{
    // then code
    using namespace std;

    cout << "Enter a number: ";
    int x; // we need x starting here.
    cin >> x;

    cout << "Enter another number: ";
    int y; // we don't need y until now
    cin >> y;

    cout << "The sum is: " << x + y << endl;
    return 0;
}

This has quite a few advantages. First, variables that are declared only when needed are given context by the statements around them. If x were declared at the top of the function, we would have no idea what it was used for until we scanned the function and found where it was used. Declaring x amongst a bunch of input/output statements helps make it obvious that this variable is being used for input and/or output.

Second, declaring a variable only where it is needed tells us that this variable does not affect anything above it, making our program easier to understand and requiring less scrolling. Finally, it reduces the likelihood of inadvertently leaving a variable uninitialized, because we can declare and then immediately initialize it with the value we want it to have.

Rule: Declare variables where they are needed.

2.2 — Keywords and naming identifiers
Index
1.11 — Comprehensive quiz

57 comments to 2.1 — Basic addressing and variable declaration

You must be logged in to post a comment.