6 minute read

Introduction

The ampersand operator & and the asterisk operator * are both useful operators that are widely used for various things related to C++. We will explain their uses in this article.

Ampersand operator &

Address of a variable

We can discover where our objects or variables are stored in the memory space by using the & operator (Ampersand) in front of our variable.

Each object or variable (like a float, int or any other data type) is stored in a certain memory address. Therefore, each time that we declare a new object or variable in our code, we are actually allocating the variable to our memory.

For instance:

#include <iostream>

int main()
{
    
    float x = 412.5241; //Stored in a memory address
    x = 5;

    std::cout << "Memory address:" << &x; //The & operator shows the memory address where myNumber is stored

    return 0;
}

If we run our code, we get:

Memory address: 0x7ffd328f5634

Each variable has got its own memory address.

Passing an object by reference to a function

We can pass an object (such as int, float, double, etc.) by reference to a function. Essentially, this means that if we modify the passed object, we are actually modifying the original object.

This can be useful when we are dealing with functions which process data and modify data inside objects because there is no need to return the object itself, as we are modifying it directly.

An example would look like this:

#include <iostream>

void modifyObject(int& obj){
    obj = 3; //Modifies the object directly
}

int main(){
    int obj = 41;
    modifyObject(obj);
    std::cout << obj << std::endl; //Returns 3

    return 0;
}

Note that if we do not use the & operator, we are actually creating a copy of the object when passing it to the function.

#include <iostream>

void modifyObject(int obj){ //Creates a copy of obj
    obj = 3;
}

int main(){
    int obj = 41;
    modifyObject(obj);
    std::cout << obj << std::endl; //Returns 41

    return 0;
}

Reference variable

A reference variable is a variable that stores the memory address of another existing object. It is important to note that:

  • A reference variable cannot point at NULL (nullptr), while a pointer can.
  • A reference cannot be re-bound to a different object and it must be bound at initialization.
  • A reference can be thought as an alias for the variable which it points to.
  • A reference doesn’t have its own address or size.
#include <iostream>
int main(){
    int myInt = 34;
    int& ref = myInt; //Creates a reference to myInt
    ref = 25;
    std::cout << myInt << std::endl; //Returns 25

    return 0;
}

Asterisk operator *

A pointer is a variable that stores the memory address of a different variable, it points to these memory addresses and provides us with an alternative way of accessing the memory space where the referenced object is stored.

Declaring pointers

Pointers are declared by using the * operator in front of the variable like: int *pointer

Note that pointer is not pointing at any variable in the example below, by default it will point at 0. For instance:

#include <iostream>

int main()
{
    
    int* pointer; //Pointer which points at 0 by default

    return 0;
}

Referencing pointers to a variable

Next, we can make our pointer reference (or point at) a variable by changing the pointer’s value to the memory address of the object that we want to point at.

This can be accomplished by running: pointer = &myNumber; For instance:

#include <iostream>

int main()
{
    
    int* pointer; //Pointer which points at 0 by default

    int myNumber = 5;

    pointer = &myNumber; //pointer equals to the address (ampersand) of myNumber

    std::cout << "It is pointing at: " << pointer << std::endl; //Shows the value of our pointer, which is the address of myNumber
    std::cout << "Memory address of myNumber: " << &myNumber; //The & operator shows the memory address where myNumber is stored
    return 0;
}

If we run our code, we get:

It is pointing at: 0x7ffffb53a0dc
Memory address of myNumber: 0x7ffffb53a0dc

As we can see, the value of our pointer and the memory address of myNumber are indeed the same.

Using pointers

Now that our pointer references a variable, we can access and modify the variable that it is pointing to by using the * operator like: *pointer

For instance:

#include <iostream>

int main()
{
    
    int* pointer; //Pointer which points at 0 by default

    int myNumber = 5;

    pointer = &myNumber; //pointer equals to the address (ampersand) of myNumber

    std::cout << "It is pointing at: " << pointer << std::endl; //Shows the value of our pointer, which is the address of myNumber
    std::cout << "Memory address of myNumber: " << &myNumber << std::endl; //The & operator shows the memory address where myNumber is stored

    *pointer = 99; //We modify myNumber which is being referenced by the pointer

    std::cout << "myNumber is: " << myNumber << std::endl;



    return 0;
}

The code snippet above prints the following to the console:

It is pointing at: 0x7ffffb53a0dc
Memory address of myNumber: 0x7ffffb53a0dc
myNumber is: 99

Finally, it is important to keep in mind that pointers are stored in the memory space too. Therefore, each pointer has its own memory address. For instance:

#include <iostream>

int main()
{
    
    int* pointer; //Pointer which points at 0 by default
    std::cout << "Memory address of pointer: " << &pointer << std::endl; //The & operator shows the memory address where pointer is stored

    return 0;
}

References

Read more about the ampersand operator here: https://www.ibm.com/docs/en/i/7.2?topic=expressions-address-operator

Read more about the asterisk operator here: https://www.cpp.edu/~elab/ECE114/Pointers%20in%20C++.html