I know what you are thinking, "I use language [insert language here] and that language doesn't use pointers" and you my friend is completely wrong. Absolutely every programming language uses pointers, it's just that some of them use pointers behind the scenes.
You see when I was finishing high-school I started learning python (python 3 to be exact). One day I stumbled upon a problem that almost made me give up on programming. Basically I had this variable that was supposed to be set by a function...
python
1a =523defsetter(p):4 p =156setter(a)78print(a)# prints 5 instead of 1
But it didn't matter how many times I called said function the variable never changed. The worst part is that when I used a dictionary it worked fine ...
python
1a ={2"b":03}45defsetter(d):6 d["b"]=178setter(a)910print(a["b"])# prints 1
After that I took a small 'vacation' from programming and sometime later I tried learning C. The neat thing is that C showed me that the problem I had with python was about pointers. Yes! The same pointers python was suppose to not be using.
So allow me to repeat myself in saying that "Absolutely every programming language uses pointers". Now with that out of the way...
What are pointers anyway?
Firstly you need a brief description of how memory, Random Access Memory (RAM) to be exact, works.
RAM crash course
You can imagine memory as a long list of locations, places where you can store data. Usually those locations can hold a single byte.
Each location has a position on the list starting at 0. So the first location is at position 0, the second at position 1, the third at 2 and so on.
That position on the list is important and is what we call a memory address. We use those addresses to tell the computer where to write to or read from.
For example you can tell the computer to write a 5 at position 10 or read the byte at position 1234567.
In a strict sense a pointer is a variable that holds a memory address, but in reality it's much more than that. A memory address is a number, an unsigned int to be exact, that can be changed through the use of operators.
Address math
Let's say you have a pointer a to the address 0, If you 1 to a now it will hold a pointer to memory address 1. If try to read from a it will return the value stored at 1 instead of 0.
So basically by changing the value of a pointer you can "move" the pointer through memory. Values that are added or subtracted to a pointer have a special name, they are called a displacement.
The important distinction here is that a pointer is a number like any other, so to make the distinction between a pointer and regular number clear some programming language have special symbols for dealing with pointer.
For example in C you use the operator & to create a pointer to a variable and the operator * to read the value at that memory location.
c
1#include<stdio.h>23intmain(){4int a =10;5int* p =&a;// Create a pointer to variable a67printf("%p %i", p,*p);// Prints the pointer ie the memory address and the value 108/*
9 * The first value will always be random, that's where the Random
10 * in Random Access Memory (RAM) comes from.
11 */1213return0;14}
Now you might be thinking how does all of this connects to the problem mentioned at the beginning? Just bear with me for a moment it will make sense at the end.
Value vs Reference
Being a variable means that we can pass pointers to a function. But as may have guessed we need a way signal to the function that the value it received is a pointer and not a regular number.
That's why the distinction between passing a pointer and passing a regular number to a function, have their own names. Passing by value is the name given to passing a regular number and Passing by reference is the given to passing a pointer.
Passing by value
This is the most common and straightforward way, where you simply pass the value stored by a variable to a function. So if you try to change the variable nothing will happen to the variable outside the function.
c
1#include<stdio.h>23voidfoo(int a){4 a +=1;// The value for a "inside" the function will change5}67intmain(){8int a =10;910foo(a);// But "outside" it nothing changed1112printf("%i", a);// Prints 10 as the function foo can't affect the variable a1314return0;15}
Passing by reference
Passing by reference is the process of passing a pointer to a function. In other words the function can directly change the value at that memory address. If you add a value to the parameter itself nothing will happen, but if you change the value at that address...
c
1#include<stdio.h>23voidfoo(int a){4 a +=1;// The value for a "inside" the function will change5}67voidbar(int* a){8/*
9 * The value for a "outside" the function will change
10 * That's because we are changing it through pointers
11 */12*a +=1;1314 a +=1;// We moved the pointer only "inside" the function15/*
16 * This function won't break that'a because the pointer was
17 * moved after we changed the the value at their memory address
18 */19}2021// Will cause an error22voidbroken(int* a){23 a +=1;// We moved the pointer only "inside" the function24*a +=1;// Will cause an error25/*
26 * This function breaks because the pointer was moved
27 * before we changed the the value at their memory address
28 */29}3031intmain(){32int a =10;3334foo(a);// But "outside" it nothing changed3536printf("%i\n", a);// Prints 10 as always3738bar(&a);// The value of a has cahnged but pointer has not been moved3940printf("%i\n", a);// Prints 114142broken(&a);// Breaks the code4344printf("%i", a);4546return0;47}
Where the problem lives
Now some questions may be going through your head if python doesn't have the & how does it know when something is a pointer or not? Is everything in python passed by values?
No, not everything is passed by value and the way python knows is through a convention. There are two groups of data in python, and other languages as well, the primitive data type and the non-primitive ones.
The most common primitive data types are numbers (int, float, double, ...), strings, char and bool. The convention is that ...
Important
If a variable holds a primitive data type then it will be passed by value otherwise they are passed by reference.
If you go back to the problem at the start you will see that the variable I couldn't change held a 5 what is a primitive data type, while the one I could change held a dictionary, a non-primitive data type.
In other words when I changed the variable that held a 5 nothing "outside" the function would change, but when I did it on a dictionary I was actually dealing with a pointer, I was actually changing the dictionary stored at that memory address.
Basically the python interpreter, when converting your code to machine code, will apply that convention to your variables without the need for you to specify what are pointers and what aren't.
That behavior is not exclusive to python because as I said all programming languages use pointers, it's just that some of them do it without asking you what should and what should not be a pointer.
Conclusion
Sometimes a language may look like it doesn't use a certain feature, but later you discover it used. That's why it's important that you learn the basics before going to something more complex.
Also at least try different languages. You don't need to be proficient in every programming language just make sure to try something new once in a while.