Pointers' power, utility, and ubiquity mean that, while they can be conceptually challenging to understand, learning them, their associated syntax, and how to use them to solve problems is nevertheless well worth the time and effort it may take. To understand pointers and the operations that can take place with them, we must first understand a little about computer memory and how programs locate variables in memory. Contemporary computer systems typically have many gigabytes of memory, and each byte of memory has a unique address. We can think of main memory or RAM as an extensive array of bytes and the addresses as the indexes of each array element or byte within the array. Most variables stored in the array (i.e., in main memory) are larger than one byte, so the address of each variable is the index of the first byte of that variable.
(a) | (b) |
The amount of memory in a computer and how the computer addresses it are physical properties of the hardware. Alternatively, the variables residing in memory are an abstraction wholly defined by software. Previously, we used houses along a street as a metaphor for the arrangement of variables in memory. Every house has a unique street address that people can use to find and distinguish it from the others on the same street. In much the same way, variables have addresses in main memory. Memory addresses are a hardware property and cannot change, but the data stored in memory - stored in a variable - can change or vary over time.
(a) | (b) |
When we write a program, we name the variables, and when we wonder about how the program works, we think in terms of the variable names. But when a program executes, the computer accesses and manipulates all data by their memory addresses. The compiler maps every variable name to a unique memory address and incorporates the address into the machine code. Together, the compiler and the operating system determine the location in memory of each variable. So, a variable is a named location in main memory with three characteristics: a name, a content, and a memory address. How the compiler interprets a variable's name - either as its address or its contents - is determined by where the name appears in a given statement.
int counter = 123; |
counter = 5; balance = counter * 10; cout << counter << endl; |
|
(a) | (b) | (c) |
Fortunately, when we write a program, we generally use the variable's name, ignoring that it has an address. But this dynamic changes when we work with pointers. A Pointer is a variable that stores or contains the address of data, possibly another variable. Pointers allow programmers to access other variables by their addresses. Any programming element (variable, object, function, etc.) stored in memory has an address that can be found and saved in a pointer. We leave unanswered, for now, the question of why we might want to access or save an element's address.
C++ provides several pointer operators, which allow programmers to define pointer variables, find the addresses of variables, and access data through a pointer. These operators are the subject of the next sections of the text.