Skip to content

Pointers

References are language features that build upon the lower level concept of pointers. A pointer is a new kind of data type, just like a struct, enum, integer, double, or boolean. A pointer value is an address, a location in memory where a value can be found. Understanding pointers will help you see how features like references work.

The name pointer is a metaphor, describing the way to picture pointer values. You can think of each pointer value as an arrow pointing to data elsewhere, with each value saying “the data I refer to is over there…“.

If you think about this, notice that each pointer has two values: the pointer’s address value, and the value at that address. Within the pointer there is an address, the place in memory that the pointer if referring to. You can then read this value, and go to that address to find the value that the pointer refers to. This means that the language needs means of interacting with these two values.

Figure x.y: A Pointer Value is the address of a value, in effect it points to a value

A Pointer Value is the address of a value, in effect it points to a value

Pointers - Why, When, and How

In C, you do not have references, so you have to use pointers to achieve similar effects. Similarly, in C++ there are limits to working with references, so you need to use a mixture of pointers and references to achieve your goals. Generally we try to avoid having to use pointers, as this will require you to have clear ways of working with memory to make sure that things don’t break. Other languages have focused more on the use of references, with different ways of helping make these more generally useful. Learning to work with pointers will help you see how references work, and help you to be aware of some of the issues that can occur when you work with references and pointers.

Pointers can be used to achieve the same mechanics as pass by reference, but would only be used for this when the language does not support pass-by-reference. In these cases you need to use a pointer to accept the address of the value you are to update, in the function or procedure you can then dereference the pointer and manipulate the value at the indicated address.

The other use for pointers is to create relationships between elements in your code. This allows you to say “I am related to that thing over there” by nesting a pointer within a struct. For example, social media platforms would set up relationships between users. Each user would be able to refer to the other users they are connected to. Here you do not want a copy of the related user, so a pointer or similar reference can establish this relationship.

What can a pointer point to?

Pointers store a value that is an address of the value that it points to. This means that you can point to any value in memory, regardless of where it is. You can have pointer values that point to local variables, global variables, parameters, fields of structs or unions.

Figure x.y: A pointer can point to any value, at any location in memory

A pointer can point to any value, at any location in memory

Where can pointer values be stored?

A pointer value is the same as any other value. It can be stored in local variables, global variables, it can be passed to a function in a parameter, and it can be returned from a function.

In C/C++

Example

The following code illustrates how to declare and use pointers. This includes pointing to local variables, and using parameters.

#include "splashkit.h"
using std::to_string;
/**
* Print the address in an int pointer, and the value it points to.
*/
void print_intp(int *ptr)
{
write_line( to_string( (unsigned long long) ptr) + " -> " + to_string(*ptr));
*ptr *= 2;
}
int main()
{
int i = 123, j = 321; // two integers
int *p; // a pointer to an integer
p = &i; // p points to i, p --> i
print_intp(p); // print and update i via p
print_intp(&i); // print and update i via address of i
print_intp(&j); // print and update j via address of i
// Verify that the values if i and j are updated
write_line("i is now " + to_string(i));
write_line("j is now " + to_string(j));
return 0;
}

This outputs the following. Notice the different addresses for the i and j variables. Notice that we are able to update the value in this variable via the p pointer, and by passing the address of i (&i) to the ptr parameter.

6134542824 -> 123
6134542824 -> 246
6134542820 -> 321
i is now 492
j is now 642