This is the first in a tutorial series on C and C++ pointers. It is written for beginning programmers to clarify pointer concepts, but is a great refresher for all programmers. It includes concrete code snippets, diagrams, and discussion text. For a more advanced, under-the-hood deep dive on arrays, pointers, and references, see this post. Let’s dive right in.
What are Pointers in C and C++?
Pointers in C and C++ are variables that point to other variables. They can also point to unnamed places in computer memory.
Foundations: What is a Variable?
A variable is an object that takes up space in computer memory, and that has a name and a type. We can assign a value to the variable, which is stored in the “cubby hole,” or memory space, reserved for it.
In the above variable definition,
c is the name of the variable, and
char is the type. The type of a variable defines both the size of the variable
in memory (for
char variables, one byte, the smallest addressable area in memory) and how it is to be handled by the compiler
(it can be assigned a letter like
'g' or a signed integer whose values can go from -128 to 127):
Above, we have defined a variable named
i of type
int. It is an object that takes up four bytes in memory, and is treated by the compiler as a
signed integer variable whose values can go from -32768 to 32767.
Note that the variable names are arbitrary, as long as they are in the proper format and do not collide with other names, such as keywords or names in libraries or other linked in code.
Variables in Memory
When the program is run, the compiler/system will place each of these variables at a certain location in memory associated with an address.
For instance, if we have 16 bytes of memory, with the first byte starting at address zero and the last byte starting at address 15
(zero to 15 inclusive is 16), the compiler/system could place
c at address two (the third byte from the bottom), and
i at address four
(the fifth byte from the bottom):
A pointer is exactly what its name implies: a pointer to something. A pointer is a variable, just like a
int variable, but its type is
pointer to type, where you specify the type:
* operator after the type (
int) is what indicates to the compiler you are defining a pointer to that type.
The type of
pc is pointer to
char, and the type of
pi is pointer to
Assigning Values to Pointers
Since pointers are variables, like
int, you must assign them a value, and the value you put in them is the address of the variable you
want the pointer to point to (you can also assign them the value
nullptr, which indicates they point to nothing):
& address of operator takes the address of a variable, so
&c returns the address of the variable
c, and here we assign it as the
value for the pointer
pc. Since the address of
c is 2, that is what gets put into
pc. Similarly, the value 4 gets put in
You can see above clearly that the value assigned to the pointer (the number put into the pointer) is the address of the variable it points to.
Pointers are Just Variables in Memory Too
Pointers are variables. In the diagram above, I put them to the side to make it easier to see the point being made: that they point to a variable and that the value stored in the pointer variable is the memory address of the variable they point to. However, Pointers are variable objects just like any other variable, so they also reside in computer memory:
As you can see, I have changed the figure to have the pointers placed in memory like any other variable, and the compiler/system has placed them at their very own respective addresses. Note that for a 16 byte total memory system, a single byte is sufficient to hold all the possible addresses, so that is how I did it in the above diagram to save space.
In a typical desktop or server system, the program would running in either a 32 bit (4 byte - for instance x86) environment, so the size of the pointer would need to be 4 bytes (the same size as an int), or a 64 bit environment (8 bytes - for instance x64), so the size would need to be 8 bytes.
Once one has pointed a pointer to another variable, one uses the
* prefix operator to retrieve the value that is inside the variable that the pointer
points to. This is called dereferencing (a pointer refers to another variable, so de-reference-ing is to change it from a reference to the
variable to the actual value of the variable it references, just as if one directly used the referenced variable itself):
Note, above I have used the shortcut notation that assigns an initial value right in the definitions of each variable. First, I define a
char variable named
c, simultaneously assigning it the value
'g'. Then, I define a pointer to
pc, simultaneously assigning it the address of the variable
Finally, I print out to the console the value of
c, directly using the variable
c itself, the contents of the pointer to
directly, which is the four byte address (in hexadecimal notation) of the variable
c, then the value of
c again, this time using the
* prefix operator to
pc, which returns the value of
c, the variable to which
Pointers can be changed at any time to point to something else, and you can assign the contents of one pointer to another:
After defining and assigning to the two
d, I define and assign the address of
pc then the address of
The first printf shows what one would expect:
pc holds the address of
pd holds the address of
*pc) returns the value of
c, and dereferencing
*pd) returns the value of
Since pointers are just variables that hold values which happen to be pointers to other variables, I can assign the value (“contents of”) one to another,
as long as they are the same type of pointers. I do this (
pd = pc), then the following
printf shows that
pd now points to
c, just like
Finally, I can directly put the address of
pc = &d) without affecting
pd: as the following
printf shows, we have ended up switching
pd point to:
pc points to
pd points to
Assigning Values Using Pointers
Finally, we show below how to change the value of the variable a pointer points to:
Just dereference (using
* prefix operator) the pointer in the assignment, and the variable the pointer points to will be updated instead of the
value in the pointer itself. Of course, the type of the value you are assigning must be the same type as the variable being pointed to,
not an address: in this case, a
char type, not a pointer to
char *) type. When we assign to a dereferenced pointer, the value
in the pointer (the address of what it points to) remains unchanged - it is the value of the variable it points to that is changed.
I hope I have accomplished my goal of providing an approachable and insightful tutorial on C and C++ pointers. If you have any corrections or constructive comments, feel free to contact me via my contact form. Next up in the series is investigating the close relationship between arrays and pointers along with pointer arithmetic.
Thanks to Pexels for the free image