For some beginners... pointers are difficult to understand.
I also experienced this when I was just learning C.
But don't worry...
I will try to explain it in language that is easy to understand.
Okay..
Let's start.
What are Pointers?
Every variable we create in the program will have a memory address.
The memory address functions to determine the location of data storage in memory (RAM).
Sometimes this memory address is called a reference.
Take a look at this picture:
In this image, we create two variables.. namely score
and hp
.
These two variables have their own memory addresses.
score
The memory address variable is 01abc
, while hp
the memory address is 02ffd
.
As long as an address is still empty... then that address will be selected.
Oh yes, the selection of this memory address is done randomly. This is why this memory is called RAM (Random Access Memory) .
In essence, every time we create a variable it will definitely have a memory address.
If you don't believe it, you can prove it yourself by using the symbol &
(ampersand) .
Example:
#include <iostream>
using namespace std;
int main () {
int a;
char b[10];
cout << "Alamat memori variabel a: " << &a << endl;
cout << "Alamat memory variabel b: " << &b << endl;
return 0;
}
In this program, we use symbols &
to retrieve the memory address of the variables a
and b
.
The result:
So what is the relationship between memory addresses and pointers?
Let's discuss…
A pointer is a special variable that contains a memory address . The pointer will later be able to access data at a memory address. 1
Keywords you need to remember:
"Pointer contains memory address"
How to Create Pointers
Pointers are created by adding a symbol *
(asterisk) in front of their name, then filled with the memory address that will be used as a reference.
Example:
int *pointer1 = 00001;
Then *pointer1
you will be able to access the data at the memory address 00001
. In other words, you *pointer1
will use the address 00001
as a reference.
We can also create pointers without having to fill them directly with memory addresses.
Example:
int *pointer_ku;
// atau bisa juga
int *pointer_ku = NULL;
So *pointer_ku
it will use a memory address 00000
, this memory address is specifically for storing data null
or empty data.
Now the problem:
Because we cannot see the memory address list directly, we will have difficulty providing memory address references for pointers.
Not to mention... different computers also have different memory addresses. There are 8 bits, there are also 16, 32, and so on.
The solution:
We have to take the memory address of another variable.
Do you still remember how?
Yes, by using the symbol &
.
Take a look at this picture:
In this image, we create a pointer with a name *ptr_hp*
containing the memory address of the variable hp
.
In this way..
The pointer *ptr_hp
will be able to access the value at the memory address 02ffd
, which is the memory address of the variable hp
.
If we want to change the value at the memory address, then we can use a pointer *ptr_hp
like this:
*ptr_hp = 95;
So, now the memory address 02ffd
will contain 95
as well as the variable hp
.
To make it clearer, let's try the exercises in the program.
Practice: Accessing data with Pointers
Create a new program with the name contoh_pointer.cpp
, then fill it with the following code:
#include <stdio.h>
int main(){
int score = 50;
int hp = 100;
// membuat pointer dengan isi alamat memori dari hp
int *ptr_hp = &hp;
// print isi variabel dan alama memori
printf("Nama Variabel \t Alamat \t Konten\n");
printf("score \t\t %x \t %d \n", &score, score);
printf("hp \t\t %x \t %d \n", &hp, hp);
printf("ptr_hp \t\t %x \t %x \n", &ptr_hp, ptr_hp);
printf("*ptr_hp \t %x \t %d \n", &ptr_hp, *ptr_hp);
// mengubah data pada alamat memori dengan pointer
*ptr_hp = 95;
printf("hp \t\t %x \t %d \n", &hp, hp);
printf("*ptr_hp \t %x \t %d \n", &ptr_hp, *ptr_hp);
return 0;
}
After that, try compiling and running it.
So the result:
The pointer *ptr_hp
successfully changes the value at the address d57ba6c
to 95
.
When using pointers, we use a sign *
in front of the pointer name to access the value at the memory address. If we don't use this flag, we will get a pointed memory address.
*ptr // ini akan berisi 95 (nilai dari alamat)
ptr // ini akan berisi d57ba6c (alamat memori dari variabel hp)
Oh yes, pointers also have their own memory address.
In the example above, the memory address of the pointer *ptr_hp
is d57ba70
. Maybe on your computer it will be different, please check it yourself.
If you look at this picture:
The memory address used *ptr_hp
is 012ef
the contents of the memory address 02ffd
.
Does anyone here understand?
Now the question:
If we use pointers, won't this waste memory? Because we have to allocate a memory address for the pointer too.
If we can use regular variables, why use pointers?
The use of pointers is actually optional, you can use them... or not.
However..
Under certain conditions, the use of pointers is more optimal.
Later we will discuss this again.
When Should I Use Pointers?
As I said earlier, we don't always have to use pointers in programs.
However, there are certain cases that suggest using pointers instead of the usual way.
Let's be clear..
Let's discuss first, why were pointers created ?
So in the past, computer memory was very limited. Not like now where the capacity is gigabytes.
When we perform iterative operations on data types such as arrays, strings, trees, linked lists, graphs, and so on... it often takes up a lot of memory and makes the program slow.
Using pointers in such operations will improve performance significantly compared to not using pointers. 1
Practice: Pointers for Pass by Reference to Functions
First we will try to use pointers to pass arguments based on their references (pass by reference) .
Example:
#include <stdio.h>
void add_score(int score){
score = score + 5;
}
int main(){
int score = 0;
printf("score sebelum diubah: %d\n", score);
add_score(score);
printf("score setelah diubah: %d\n", score);
return 0;
}
In this program, we create a function with the name add_score()
to add the score value by 5
.
But when run:
The value of the score variable does not change, it remains valuable 0
.
Why?
This is because we are doing pass by value , not pass by reference .
Variables score
are created inside functions main()
, then when the function add_score()
tries to change their values...
…then changes only occur locally within the function add_score()
.
Do not believe?
Try to prove it by changing the function add_score()
to something like this:
#include <stdio.h>
void add_score(int score){
score = score + 5;
printf("Score diubah ke %d\n", score);
}
int main(){
int score = 0;
printf("score sebelum diubah: %d\n", score);
add_score(score);
printf("score setelah diubah: %d\n", score);
return 0;
}
The result:
It's true what I said...
The value score
in the function add_score()
has changed to 5
, but the variable score
in the function main()
will still have the value 0
.
Now..
This is where we have to use pointers to do pass-by-reference .
Now, try changing the program code to be like this:
#include <stdio.h>
void add_score(int *score){
*score = *score + 5;
printf("score diubah ke: %d\n", *score);
}
int main(){
int score = 0;
printf("score sebelum diubah: %d\n", score);
add_score(&score);
printf("score setelah diubah: %d\n", score);
return 0;
}
Because we convert function arguments add_score()
into pointers, we must provide a memory address when calling it.
So the result is:
Every time a function add_score()
is called or executed, the variable value score
will increase 5
.
Let's try changing it to something like this:
#include <stdio.h>
void add_score(int *score){
*score = *score + 5;
printf("score diubah ke: %d\n", *score);
}
int main(){
int score = 0;
printf("score sebelum diubah: %d\n", score);
add_score(&score);
add_score(&score);
add_score(&score);
add_score(&score);
add_score(&score);
add_score(&score);
printf("score setelah diubah: %d\n", score);
return 0;
}
The result:
Practice: Pointers for Accessing Data in Arrays
Pointers are also often used to access data in arrays.
Example:pointer_array.cpp
#include <stdio.h>
int main(){
printf("## Program Antrian CS ##\n");
char no_antrian[5] = {'A', 'B', 'C', 'D', 'E'};
// menggunakan pointer
char *ptr_current = no_antrian;
for(int i = 0; i < 5; i++){
printf("📢 Pelanggan dengan no antrian %c silakan ke loket!\n", *ptr_current);
printf("Saat ini CS sedang melayani: %c\n", *ptr_current);
printf("-------- Tekan Enter untuk Next --------");
getchar();
ptr_current++;
}
printf("✅ Selesai");
return 0;
}
In this program, we use it ptr_current
to access array elements. When first created, the pointer ptr_current
will reference the first element of the array.
Then in the loop an increment is carried out ptr_current++
, then this pointer will reference the next array element.
The result:
Practice: Pointers for Accessing Data in Structs
Using pointers in structs will help us make code easier and easier to read than without pointers.
As an example..
For example, we have a struct like this:
struct Player {
char *name;
int score;
int hp;
struct Weapon *weapon;
};
struct Weapon {
char *name;
int attack;
int guard;
};
The struct Player
inside there is another struct, namely struct Weapon
. Well here we use pointers for structs Weapon
.
struct Weapon *weapon;
The question:
How do I access data in struct weapon?
There are two ways, we can use the .
(dot) operator and ->
the (pointer operator).
First, let's try using dots.
Please create a new program with the name pointer_struct.cpp
, then fill it with the following code:
#include <iostream>
using namespace std;
int main(){
struct Weapon {
string name;
int attack;
int guard;
};
struct Player {
string name;
int score;
int hp;
Weapon *weapon;
};
Player player1;
player1.name = "Petani Kode";
player1.score = 0;
player1.hp = 100;
player1.weapon = new Weapon;
(*player1.weapon).name = "Katana";
(*player1.weapon).attack = 16;
(*player1.weapon).guard = 10;
// cetak status player
cout << "PLAYER STATUS" << endl;
cout << "Name: " << player1.name << endl;
cout << "Score: " << player1.score << endl;
cout << "HP: " << player1.hp << endl;
cout << "Weapon" << endl;
cout << " name: " << (*player1.weapon).name << endl;
cout << " attack: " << (*player1.weapon).attack << endl;
cout << " guard: " << (*player1.weapon).guard << endl;
return 0;
}
After that, compile and run.
So the result is:
Pay attention to the code!
When we access member data in a struct that is in the form of a pointer with the dot operator, we have to use parentheses *
to state that it is a pointer.
(*player1.weapon).name = "Katana";
(*player1.weapon).attack = 16;
(*player1.weapon).guard = 10;
If only one member is a struct pointer, this is fine.
But..
If, for example, there is a struct pointer member and inside it there is a struct pointer and inside it there is a struct pointer, we will definitely be confused.
The code could be like this:
(*(*(*player.weapon).katana).type).name = "Wakizashi";
Duh! I'm just confused reading it.
So, so it's not like this... we can use the arrow operator ( ->
) to access members of a struct that uses pointers.
Example:
player->weapon->katana->type->name = "Wakizashi";
This is easier to read than the previous one.
So, if there are member pointers in the Struct, then you should use operators ->
to access the members.
Let's change the previous code ( pointer_struct.cpp
) to be like this:
#include <iostream>
using namespace std;
int main(){
struct Weapon {
string name;
int attack;
int guard;
};
struct Player {
string name;
int score;
int hp;
Weapon *weapon;
};
Player player1;
// membuat pointer untuk player1
Player *p1 = &player1;
p1->name = "Petani Kode";
p1->score = 0;
p1->hp = 100;
p1->weapon = new Weapon;
p1->weapon->name = "Katana";
p1->weapon->attack = 16;
p1->weapon->guard = 10;
// cetak status player
cout << "PLAYER STATUS" << endl;
cout << "Name: " << p1->name << endl;
cout << "Score: " << p1->score << endl;
cout << "HP: " << p1->hp << endl;
cout << "Weapon" << endl;
cout << " name: " << p1->weapon->name << endl;
cout << " attack: " << p1->weapon->attack << endl;
cout << " guard: " << p1->weapon->guard << endl;
return 0;
}
The result:
In this program we create two variables for the Player struct, namely player1
and p1
. The variable p1
will be a pointer to access data on player1
.
// membuat struct player
Player player1;
// membuat pointer untuk player
Player *p1 = &player1;
Because p1
it is a pointer that references a struct player1
, we can access the members player1
with the arrow operator ( ->
).
What is next?
We have discussed the basic concept of pointers in C++. You have to understand this concept, so that later when you meet pointers you won't be confused.
We don't always have to use pointers, but there are certain cases such as data access in Structs... using pointers is highly recommended so that the code is easier to read.
If you are still confused, please ask in the comments.
Next, please learn about memory allocation with the functions malloc()
, calloc()
, realloc()
, and free()
.
Happy learning. 🙌
Post a Comment