« Understand pointers in C++ the right way

Understand all whats needed about pointers the right way.

Step 1 → Understand variables and symbol table in C++

1int i = 20;

This means I am asking system I need a variable and please put 10 there.So system will create a 4 byte storage for me and will put 10 at that memory location.

Here "i" is the way through which we get know where it is stored.

symbol_table.jpg

This is called symbol table. This is made at compile time. At compile time itself it is stored where i or j or k will be stored. So if I need to get i then I will go to symbol table and get that its memory location which is 700 and symbol table will also tell that we need to read a int variable so system will read it as a integer variable.

For every variable that you are creating the system is storing where is the variable actually stored in memory and it also stores the type of the variable also. So, whenever we will talk about i variable we will know it is stored at memory location 700 and it is also a integer so I will go to the location 700 and we will read 4 bytes as integer takes 4 bytes in memory


Step 2 → Understand addressof operator

1int j;
2cout << &j << endl; // addressof operator.

Even if i don't put any value in j still a memory location is given to j. This is in hexadecimal. Hexadecimal means 16 base. So it will start from 0,1,.....,9a.....f where f means 15 e means 14 and so on

heax_deci_convert.jpg


Step 3 → Understand what pointer is

1int *p;
2p = &j;

The way I am storing integer in int and character in char. The same way I want to store address in some type of variable. So pointers are variables which can store address of other variables. Now we have two ways to reach the same memory location

ptr_intro.jpg

int * p(means p is a pointer(*) to a integer(int))

pointer_reading_way.jpg

1cout << p << endl;
2cout << &j << endl;

As you can see value of p and address of j will come out to be same.

1float f = 10.2;
2float *pf = &f;
3double d = 10.2;
4double *pd = &d;

The same way we create integer pointer we can create float or double pointer.

Step 4 → dereference operator

1cout << "*pf: " << *pf << endl;

This is dereference operator. This will get the value from the location whose address is stored in the pointer.

Step 5 → Understand how pointers are stored

1int k = 20;
2int *ptr = &k;

pointer_memory_location.jpg

Like integer, character, float and double, pointer is also stored at some memory location.

Step 6 → Size of a pointer

1cout << "sizeof(k): " << sizeof(k) << endl;
2cout << "sizeof(ptr): " << sizeof(ptr) << endl;

As integers have size of 4 bytes and doubles has size of 8 bytes, the same way size of a pointer can be 4 or 8. This is closely related to 32 or 64 bit but that also is not compulsory.


Step 7 → More about pointers

1int k;
2int *ptr = &k;
3cout << "k: " << k << endl;
4cout << "*ptr: " << *ptr << endl;

k or *ptr point to same 4 bytes. So we can go either with k or *ptr

1(*p)++

We can treat *p exactly as integer.

1int k;
2int *ptr = &k;
3cout << "k: " << k << endl;
4cout << "*ptr: " << *ptr << endl;
5int *qtr = ptr;

qtr is also pointing to k like ptr. Here qtr, ptr and k all are pointing to the same 4 bytes. So *ptr++ *qtr++ k++ all are just the same.

qtr_ptr_k.jpg


Step 8 → NULL pointers

1int b;
2cout << "b:" << b << endl;
3b++;
4cout << "b:" << b << endl;

Some garbage value as nothing is being set as value.

1int *m;
2cout << "m: " << m << endl;

Some garbage address will be there

1cout << "*m: " << *m << endl;
2(*m)++;

This can be fishy. We are trying to print value at some garbage address. May be this address doesn't comes into our program range. May be this address is a readonly memory and we are trying to tamper with it. This is too risky we should not do like this. This may give error or may be not.

This means m is pointing to some random garbage address and we are changing the value at that address. This is not my memory and we are trying to change it. May be value will change or may be not, depends on how critical location its pointing to.

1int *n = 0;
2cout << "n: " << n << endl;
3cout << "*n: " << *n << endl;

So whenever we are creating any pointer we either save some address into it and if there is nothing to store at current point of time then please assign it to 0(null address) means its pointing to nowhere. So if you perform *n then it will give error always as there is no address here as null address value is given. This will always give error.

FINAL CODE

1#include <iostream>
2#include <iomanip>
3#include <algorithm>
4#include <string>
5#include <cstring>
6#include <vector>
7#include <cmath>
8#include <map>
9#include <climits>
10// climits for INT_MIN
11#include <unordered_map>
12using namespace std;
13int main()
14{
15 int i = 20;
16
17 i = i + 5;
18 cout << "i= " << i << endl;
19
20 int j;
21 cout << &j << endl; // addressof operator.
22
23 int *p;
24 p = &j;
25
26 cout << p << endl;
27 cout << &j << endl;
28 // As you can see value of p and address of j are same
29
30 float f = 10.2;
31 float *pf = &f; // float pointer
32
33 double d = 10.2;
34 double *pd = &d; // double pointer
35
36 cout << "*pf: " << *pf << endl; // dereference operator.
37
38 int k = 20;
39 int *ptr = &k;
40
41 cout << "sizeof(k): " << sizeof(k) << endl;
42 cout << "sizeof(ptr): " << sizeof(ptr) << endl;
43 // it can be 4 or 8. Closely related to 32 or 64 bit but that also is not compulsary.
44
45 k++;
46
47 cout << "k: " << k << endl;
48 cout << "*ptr: " << *ptr << endl;
49
50 int a = k;
51 // we can also write *ptr. k or *ptr point to same 4 bytes
52 a++;
53
54 cout << "a: " << a << endl;
55 cout << "k: " << k << endl;
56
57 *ptr = 25;
58 cout << "k: " << k << endl;
59 cout << "*ptr: " << *ptr << endl;
60
61 (*ptr)++;
62 cout << "k: " << k << endl;
63 cout << "*ptr: " << *ptr << endl;
64
65 int *qtr = ptr;
66
67 int b; // some garbage value
68 cout << "b:" << b << endl;
69 b++;
70 cout << "b:" << b << endl;
71
72 int *m; // some garbage address will be there
73 cout << "m: " << m << endl;
74 cout << "*m: " << *m << endl;
75 (*m)++;
76
77 cout << "*m: " << *m << endl;
78
79 int *n = 0;
80 cout << "n: " << n << endl;
81 // cout << "*n: " << *n << endl;
82 // This will always give error*/
83
84 return 0;
85}