Pointers for dummies, Easier than you think!

C++ProgrammingWritten by luna
Thumbnail

In this article, we are going to talk about the most over-complicated thing in computing These are pointers!

Thisisavisualrepresentationofwhatpointersarelikeinsideyourprocess’smemory.
This is a visual representation of what pointers are like inside your process’s memory.

So, what is a pointer?

Pointers can simply be explained in 10 words: “A variable that holds a memory address as a value.”

Here's a little diagram to explain it:


Value = The data stored at the Address

Address = Where the data “lives” in the memory

You may be wondering why the Addresses all begin with 0x, and it’s simple to indicate that it is following a Value written in Hexadecimal, aka Base 16. If you want to learn more about this, I will be making an article teaching Hex along with binary, so look out for that!


So, as we see in the diagram in the Address of 0x100000, we have the value of 1,

In the Address of 0x1007F8, we have the Value of 0x100000, which has the value of 1.

Address 0x1007F8 is known as a Pointer Because it holds the value of an Address.


It’s as simple as that! 😜


If you still don't get it, here's another personal favourite metaphor I love:

“A pointer is very much like a shortcut on a desktop.”


So now that you know that Pointers point to a specific address in memory, let’s talk more about them!


The size of the pointer depends on the architecture chosen, e.g., 32 Bits = 4 bytes, 64 Bits = 8 bytes.

The reason why this is the case is that the size is dependent on the size.


NOT the size of the variable space, but the maximum addressable space.


We can also point to a place where we want to allocate memory, which is called dynamic memory allocation. We will discuss the uses of pointers later in this article!

When declaring a pointer, you always want to set it to a Null pointer. A null pointer simply doesn't point to anywhere. We can represent that in a lot of ways!

int main()
{
int* Pointer1 = nullptr; // #1 ***nullptr == 0***
int* Pointer2 = NULL; // #2 ***NULL == 0***
int* Pointer3 = 0; // #3

return 0;
}

These all mean the same thing and you can interchange them, But I highly suggest using the first option, nullptr, Which is a lot easier to read and if you ever work with people on a project they will love you a lot more for using it, We want to declare the pointers before use for the same reason! It’s conventional, and we want to stick to this for easier-to-read code!


De-referencing a null pointer can lead to undefined actions. Avoid it due to it possibly leading to application crashes.

Pointer Declaration/De-referencing

As you saw in the previous example, I used something that u may not have seen if you’re a beginner, and that is int*. The important thing is the ‘ * ’,

In that example we where declaring a pointer which is holding a de-referenced value of int, Then we gave the pointer a name in our example i used “Pointer1”, “Pointer2” and “Pointer3”, Then gave it where the pointer points too, In that case we declared it so gave it a NULL path.

&variableName

The ‘&’ Basically just means address, so reading this, it would be the Address of the variable.

int* pointerName

Creating an int* like we talked about in the previous part!

*pointerName

This syntax is for dereferencing a pointer. De-referencing just means accessing the value at the memory address

So let’s do this again after learning about these syntax rules:

#include <iostream>

int main()
{
int foo = 4; // Declaring an int variable with value 4
int* pFoo = nullptr; // Declaring a pointer named pX

pFoo
= &foo; // Assigning The Address of variable X to pX, we get the address with '&'

std
::cout << "Current Value of Variable X: " << foo << "\n";

*pFoo = 3; // The dereferenced pointer of pX = 3

std
::cout << "Address of X" << pFoo << "\n";

return 0;
}

So, how does this look inside the memory?

Well, first let’s look at our foo memory block:

Address Value

As you can see, in the memory address on the left, we are storing the value [04 00 00 00] in the 4 bytes we allocated for that address


This is the Address and Value of the Pointer “pFoo”. You can read the address if you know about little-endian and big-endian.

If you don't know about the endian we will be writing an article on it so be on the look out!

Why Do We Even Use Pointers?

There are many reasons why we use pointers in programming. Efficient memory management is one of the primary benefits of pointers, as they allow programmers to directly read from and write to specific memory locations, giving precise control over how memory is allocated and deallocated during program execution.


Performance optimization is another significant advantage of using pointers, because accessing data directly through memory addresses is considerably faster than making expensive copies of data, which can dramatically improve execution speed for programs working with large amounts of information.


Pointers also enable calling functions by reference rather than by value, which means functions can modify the original variables passed to them instead of working with temporary copies, making it possible to create functions that can change multiple values and return them to the calling code.


When working with arrays, particularly character arrays used for strings, pointers provide a more intuitive and flexible approach to manipulating data elements, allowing for operations like substring extraction or string concatenation without unnecessary memory overhead.


Finally, pointers are absolutely essential when implementing complex data structures such as linked lists or trees, where elements need to reference other elements dynamically, creating relationships that would be impossible to represent efficiently without the ability to store and follow memory addresses.

How Do We Manage Memory?

Memory management is an important aspect of coding in every language, but especially in low-level languages such as C/C++, where you don't have an automatic garbage collector.

So, to prevent memory leaks and other bugs, we MUST use efficient Memory management. We use pointers!

You may have seen I have always typed Pointers, but only showed two types, both of which are Raw pointers. Well… there are a lot more different types of pointers. Some of the most common ones would be:

int* pointerName = NULL;

Null pointer (a pointer that doesn't point to any valid address)

void* pointerName

Void pointer (a pointer that can hold the address of any data type)

int* pointerToMyFavouriteNumber = new int(69);
delete pointerToMyFavouriteNumber;

// Try to access the deallocated value
*pointerToMyFavouriteNumber // will result in unexpected behaviours

Dangling pointer (a pointer that is accessing freed memory)

std::unique_ptr<int> pointerToFoo = std::make_unique<int>(69);
// This way, memory is automatically cleaned up when pointerToFoo goes out of scope

Smart Pointers (automatically de-allocating objects when out of scope)

int foo()
{
int goo = 5;
return goo;
}

int (*FunctionPointer)() {&foo}; // Function Pointer pointes to the funciton & of foo

Function pointers (a pointer that points to a function instead of a variable)

Don’t be scared of Smart Pointers! 👻

First, let’s look at a Smart pointer and what it really does. In modern C++, we use Smart pointers to abstract away the ownership of addresses. You may not know what this means, don't worry, smart pointers are complicated at the beginning of your journey.


I also said it automatically de-allocates itself when out of scope, but what does that mean? And why do we need to deallocate it well? Not freeing that pointer will lead to Dangling pointers.

These Dangling pointers, if dereferenced, will have undefined actions, and if you write to them, it may cause Memory Corruption, which may lead to crashes in your program.

But to quickly sum it up,


*️⃣ Instead of holding an address like a Raw pointer, A smart pointer owns the address and takes responsibility for allocating the memory, along with de-allocating the memory automatically, so you don't need to manage it manually.


I will write more about Smart Pointers in another article in the future!

Conclusion

You should have the idea of what a pointer is now!


💡 But remember, the best way to solidify your knowledge is to go out and experiment with pointers in your own code!


If you wish to learn more about C++ programming and want to enroll in a course, we highly suggest checking out our Doctrina to C++ Programming course.

Thank you for reading this article and I hope it helped you learn more about pointers if you were confused!



PREVWindows API - A Deep Dive
NEXTThere's nothing more...

Our FAQ

Frequently asked questions

Get answer to the most common questions about Haxo Games and our services

Start learning today

Start learning today and follow your dream future to become a professional in Cybersecurity through interactive lessons and CTF challenges

line
rays