C++ Pointers
Tags: cpp
Published: 2020-12-18 18:03:52

---
title: C++ Pointers
published: true
description: C++ Pointers
tags: cpp
series: C++ Journey
//cover_image: https://direct_url_to_image.jpg
---

Pointers are variables that hold memory addresses of data as opposed to the data itself. In other words, the pointer variable *points* to the location of the data.

The syntax to declare a pointer variable is `dataType *identifier`.

The `*` can be anywhere between the `dataType` and `identifier`.

```
int* p;
int * p;
int *p;
```

In order to assign a value to a pointer, you need to use the *address of* operator: `&`.
The *address of* operator is a unary operator that returns the address of its operand.

For example, if you assign `10` to the integer variable `num` and output `num` prefixed with the *address of* operator, you will see the memory address storing `num`.

```
int num = 10;

std::cout << &num;

// output:
0x7ffeefbff538
```

`0x7ffeefbff538` is the memory address holding the value of `num`. The hexadecimal value represending the memory location will be different for you because it won't be storing the data in your machine at the same location as mine.

You can use a pointer variable to store the memory address:

```
    int num = 10;
    int *numPtr = &num;
```

The pointer data type has to match the data type of the variable it's pointing to.

```
    double num = 10.75;
    double *numPtr = &num;

    char ch = 'A';
    char *chPtr = &ch;
```

If you output the value of `numPtr` you would get the same memory address as outputting `&num`. In order to retrieve the value `10` you need to dereference the pointer variable. The *dereferencing operator* is the `*` (asterisk) like the one used to create a pointer.

```
    int num = 10;
    int *numPtr = &num;

    std::cout << *numPtr << std::endl; // 10
```
Here is a comparison of outputs:

```
    int num = 10;
    int *numPtr = &num;

    std::cout << "&num: " << &num << std::endl;
    std::cout << "numPtr: " << numPtr << std::endl;
    std::cout << "&numPtr: " << &numPtr << std::endl;
    std::cout << "*numPtr: " << *numPtr << std::endl;

// output:
&num: 0x7ffeefbff538
numPtr: 0x7ffeefbff538
&numPtr: 0x7ffeefbff530
*numPtr: 10
```

You can see that the value of `numPtr` is the memory address of num, printing the memory address of `numPtr` shows the memory address of the pointer variable, and dereferencing `numPtr` gives the value stored in `num`.

You can use pointers with classes and structs, too.

```
struct DogType
{
    string name;
    char breed;
    int age;
};

DogType dog;
DogType *dogPtr = &dog;


dog.name = "Penny";

std::cout << dog.name << std::endl; // Penny

(*dogPtr).name = "Pixel";

std::cout << dog.name << std::endl; // Pixel;
```

You can see that in order to use the pointer to set a new value in the memory address the pointer is pointing to, you have to put parentheses around the derefercing of `dogPtr`. This is because, in C++, the dot operator `.` has a higher precedence than the dereferencing operator `*`. By using the parentheses, the dereferencing operator will evaluate first.

Thankfully there is an easier way to write this, using the *member access operator arrow ->

```
// (*dogPtr).name = "Pixel";
// becomes

dogPtr->name = "Pixel";
```

So, why bother with any of this when you can just directly access/modify the variable that's being pointed to?

By using pointers, you can create *dynamic variables*, which are variables created during program execution. Dynamic variables are unnamed and must be accessed indirectly by pointers.

The keyword `new` is used to create dynamic variables by allocationg memory in the heap.

You can use `new` to allocate memory for a single variable or for an array of variables.

```
int *p = new int;

int size = 10;
int *pArray = new int[size];
pArray[0] = 1;
```

The code below asks the user to press 1 to create a new dog. Each time a dog is created with the `new` operator, the memory address is stored in `dogPtr`.
```
    int input = -1;

    DogType *dogPtr;

    while(input != 2)
    {
        std::cout << "Press 1 to create a new dog: ";
        std::cin >> input;

        if (input == 1)
        {
            dogPtr = new DogType;
            dogPtr->name = getDogName();
            std::cout << "I'm a new dog and my name is " << dogPtr->name << endl;
            std::cout << "dogPtr is located at " << dogPtr << endl;
        }
    }

    return 0;
}

// output:
Press 1 to create a new dog: 1
I'm a new dog and my name is Elaine
dogPtr is located at 0x1006040e0

Press 1 to create a new dog: 1
I'm a new dog and my name is Murray
dogPtr is located at 0x1004045a0

Press 1 to create a new dog: 1
I'm a new dog and my name is Guybrush
dogPtr is located at 0x1004045c0

```
As you can see, each time a new dog is created it's stored in a new memory address. An important thing to note is when you use `new` to allocate memory you need to use `delete` to deallocate that memory when you're done with it. Otherwise, when you point the pointer variable elsewhere, that initial memory space will still be taken and you'll have no way to access it. This is known as a **memory leak**.

If you delete an object in memory, but a pointer still points to that memory address, you end up with a **dangling pointer**, which could cause corrupted data or program termination.

### nullptr
C++ doesn't initialize variables; therefore, pointer variables must be initialized to prevent them from accidentally pointing to some place in memory you didn't intend.

```
int *p = 0;

// is equivalent to

int *p = NULL;

```

The C++11 standard introduced `nullptr`:

```
int *p = nullptr;
```

### Pointer Arithmetic

You can do some arithmetic on pointers for operations, but it doesn't work the same way as it does on data types such as `int` and `double`.

If you increase an int value by 1, it will increase by 1.

```
int num = 1;
num++;
std::cout << num << std::endl;


// output
2
```

When you increase a pointer by 1, it increases by the size of the data type it's pointing to.

If you have an array the pointer will point to the memory address of the first index. Since this example is an array of integers and an int is 4 bytes, when you increase the pointer by 1 it will increase the memory address by the size of an int to point to the next index in the array.

```
int *p = new int[10];

cout << p << endl;

p++;

cout << p << endl;

// output
0x1030bd1c0
0x1030bd1c4
```

You can see by the last digit of the output that the memory address increased by 4.

Pointer arithmetic can be dangerous because you could end up accessing the memory where other variables are stored and altering their values.

### Further Reading / References
* C++ Programming: Program Design Including Data Structures 8th ed. by D.S. Malik
* [Pointers - Microsoft Docs](https://docs.microsoft.com/en-us/cpp/cpp/pointers-cpp?view=msvc-160)
* [The Stack and the Heap](https://www.learncpp.com/cpp-tutorial/79-the-stack-and-the-heap/)