Contact
Evil Genius SocietyHomeLearnForumLeaderboardSocialsMessages
← Back to module

Lesson 1 of 6

Every variable your program creates lives somewhere in memory. Memory is one enormous numbered row of bytes, and the number of the byte where a variable starts is its address.

That is the whole idea. Everything else in this module is notation for it.

The row of boxes

Picture memory as a street of houses, each holding one byte, each with a house number:

address:  1000   1001   1002   1003   1004   1005   1006   1007
        +------+------+------+------+------+------+------+------+
value:  |  42  |  0   |  0   |  0   |  7   |  0   |  0   |  0   |
        +------+------+------+------+------+------+------+------+
         \___________________/       \___________________/
              int x = 42                  int y = 7
              at address 1000             at address 1004

An int is 4 bytes (lesson 3.2), so x occupies 1000–1003 and y occupies 1004–1007. The address of a variable is where it starts: x is "at 1000", not "at 1000 through 1003."

The real numbers are much larger and differ every run. The shape is what matters.

Taking an address

The & operator answers "where does this live?":

#include <iostream>

int main() {
    int x = 42;
    int y = 7;

    std::cout << "x holds " << x << "\n";
    std::cout << "y holds " << y << "\n";

    // &x is the address of x. Printing it gives a number that changes every run,
    // so compare instead of printing.
    std::cout << "x and y are at different addresses: " << (&x != &y) << "\n";
    std::cout << "an address is " << sizeof(&x) << " bytes on this machine\n";
    return 0;
}
x holds 42
y holds 7
x and y are at different addresses: 1
an address is 8 bytes on this machine

Two things to take from that output.

Addresses are values. &x produces a number you can store, pass to a function, and compare — just like 42 is a number. That is the entire premise of pointers (lesson 7.2).

An address is 8 bytes here. Not 4, not the size of an int. On a 64-bit machine an address is 64 bits regardless of what it points at. The address of a char and the address of a 1000-element array are the same size, because both are just house numbers.

Why the numbers change every run

Print an actual address twice, on two runs, and you will usually get different values. That is deliberate: modern operating systems randomise where a program's memory is placed (address space layout randomisation) to make attacks harder.

So never write a program whose behaviour depends on a specific address, and never write a lesson whose expected output contains one — which is why every example here compares addresses rather than printing them.

Addresses are ordered, but only within one object

You can compare addresses with < and >. Within a single array the result is meaningful:

#include <iostream>

int main() {
    int values[4] = {10, 20, 30, 40};

    std::cout << (&values[0] < &values[1]) << "\n";
    std::cout << (&values[3] > &values[0]) << "\n";

    // Elements sit next to each other, so the gap between neighbours is one int.
    std::cout << (&values[1] - &values[0]) << "\n";
    return 0;
}
1
1
1

That last line is the surprise: &values[1] - &values[0] is 1, not 4. Subtracting addresses counts elements, not bytes. Lesson 7.4 is entirely about why.

Comparing addresses of two unrelated variables (&x < &y for separate locals) is not meaningful — the compiler is free to lay them out in any order, and the standard does not define the comparison. Do not build logic on it.

What this buys you

A value you can hold that says "the thing over there" unlocks four things you cannot do otherwise:

  • Let a function change its caller's variable rather than a copy (lesson 5.3 did this with references; now you will see what a reference is made of).
  • Pass something large without copying it — an address is 8 bytes however big the object is.
  • Ask for memory while the program is running, when you do not know at compile time how much you need (lesson 8.3).
  • Say "nothing here" — an address that deliberately points at no object (lesson 7.2).

Try it

Declare an int, a double, a char, and an array of 10 ints. Print the sizeof of each variable and the sizeof of each variable's address. Predict the numbers before you run it.

Checkpoint

  • Memory is one long numbered sequence of bytes; a variable's address is where it starts.
  • &x yields the address of x, as a value you can store, pass, and compare.
  • An address is 8 bytes on a 64-bit machine, regardless of what it points at.
  • Real address values change between runs; never depend on a specific one.
  • Subtracting two addresses in the same array counts elements, not bytes.

Questions about this lesson

Log in to ask a question.