Make sense of pointers

Let’s have a look at “low-level stuff”.

You know what they say, you want something in C, do it yourself!

Disclaimer

There won’t be any diagrams. I want to insist on what pointers are and why they are useful, and how I understand them. It’s not about code and every possible way to use pointers in C.

Lets start with arrays

Arrays are handy. We use them to store multiple values:

#include <stdio.h>

int main () {
	int arr[] = {13,27,51};
	printf("%d\n", arr[2]);
	printf("%d\n", *(arr + 2));
	return 0;
}

Run this code, and you’ll see that arr[2] is the same as *(arr + 2). All languages built on top of C, a.k.a the C-family programming languages, follow that fundamental principle.

While you won’t see pointers in those high-level languages, they are all over the place in C.

N.B.: *(arr + 2) stores the address of the first element in the third row

Make sense of memory

What is the computer’s memory? It’s essentially a certain amount of bytes, and each byte gets a reserved address. The program will store contents (a.k.a values) in those addresses.

RAM stands for random access memory. Every time you change or execute something on your computer, you are using RAM, but it gets lost if you switch off your machine. That’s why you need to save your work in files, which live on the disk drive (hard disk).

Make sense of pointers in memory

When you add variables, you ask for a certain amount of space (bytes) in memory (RAM). We just saw each byte gets a reserved address in memory.

You can see bytes as cells, so the memory is nothing more than a colossal array composed of cells. Every cell has its location (~ its address). If you point to that address, you get that cell and what it holds.

Because computers only understand 0 and 1, those cells hold binary representations of strings, integers, or any valid data types you might use.

N.B.: It’s not 100% accurate, but that should give you some hints.

Pointers as addresses

When you write:

#include <stdio.h>
 
int main () {
	int number;
	number = 111;
	int* pointer = &number;
	printf("%p\n", pointer);
	return 0;
}

You ask for some bytes in memory. You call that group of bytes “number”, and you put “111” in it. Then you create a pointer with an integer type that holds this group address in memory.

If you execute that program, you will get something like 0x7ffeedfe58a8, but what the heck can you do with this address?

What’s the point of pointers?

Pointers are powerful. We don’t need to copy variables over and over to use them. We know exactly where they are in memory, so we can easily manipulate them, and changes take effects everywhere it should.

Do not repeat yourself (DRY)!

Imagine that you store a lot of data in a variable, e.g., a big array. Instead of copying it every time you need it and kill memory, you would have a better approach and point to where it already lies in memory.

Function pointers in C

In C, function pointers allow for a callback mechanism. In other words, you can call your functions for a specific event. It’s useful because, in C, you don’t have any run-time representation.

It’s also useful to reduce code clutter (eliminate the too many if/else and switch statements).

The syntax is quite weird, though. You use something like:

<return_type> (*<pointer>) (args);

Conclusion

I’m not going to lie. You might not fully understand pointers until you use them for real, but, hopefully, this introduction gave you some hints.

This concept is quite central in computer science, and not easy to master, especially in C.