Understanding the pointers in C
Tags: c, programming, beginners, tutorial
Published: 2024-03-03 20:18:25

**Hello coding pals 👋**

Today I'm going to give you a comprehensive yet simple guide to pointers in C.

Before proceeding, make sure you are alt-east familiar with some basic c syntaxes like `printf`, `scanf`, `main` and user defined functions.

Understanding this will help you to deal with pointers in other languages as well. 😌

Aright then!, let's begin shall we?

**First of all, what's a pointer?**

Our computer programs are usually using the  main memory(RAM) when they are executing.

The variables we assign in programs are stored in the main memory.

So, when a variable is stored in the main memory, there is an address for that memory location where the variable is located in our main memory.

That address is what we use to access the value which stored in that variable.

A pointer's job is to provide a point to that exact address so we can access the value in that variable.


![Pointers visual representation - credits: GeeksforGeeks](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1p1tl2iqabjj8tzwfb16.png)

image credit: [geeksforgeeks.org](https://www.geeksforgeeks.org)

The above image shows the difference between a pointer variable and a normal variable that pointer points to.

NOTE: A pointer variable also occupies system memory, which gives it a memory address too. so we can even create another pointer variable to an already specified pointer variable as well.

> **So simple terms, a pointer is a variable that stores a memory address.**

Enough theory, now let's jump into practical examples to better understand how pointers works in a programming environment. 

We're going to use C as our programming language since it's one of the few languages that offers direct memory manipulation where proper use of pointers are needed.

```c
#include <stdio.h>

int main()
{
    int b = 42;

    int *a;

    return 0;
}
```

Study the above code.

Inside our main function, I have created a `int` type variable named `b` which stores the value `42`.

after that, I have created another `int` type variable named `*a`. 

You'll notice few differences in the declaration syntax.

`*` means make it a pointer, So `*a` means make `a` a pointer. And `int` means `a` is going to point to `int` values.

With the above code nothing will happen actually. Bcuz we're just telling a is an `int` pointer. We haven't tell it to where it should point to.

Let's see how we do that now.

```c
#include <stdio.h>

int main()
{
    int b = 42;

    int *a = &b;

    return 0;
}
```

Now in the above code you'll notice I have added another thing to the end of the pointer variable declaration.

This `&` operator is used to get a memory address of a certain variable.

So `&b` means we are telling to get the memory address of `b`.

So, the complete line `int *a = &b;` means to create a pointer variable named `a` that points to an `int` value and assign the memory address of `b` to it.

Theoretically, now `*a` should have the exact memory address of `b`.

We can verify this by printing the both `b`'s memory address and `*a`'s memory address.

```c
#include <stdio.h>

int main()
{
    int b = 42;

    int *a = &b;

    printf("b: %d\n", b); // prints the value of b
    printf("&b: %p\n", &b); // prints the memory address of b
    printf("a: %p\n", a); // prints the value of a

    return 0;
}
```

If compile and run the above code, You'll get the following output. (your memory addresses may be vary)

```
b: 42
&b: 0x7ff7b3c403c8
a: 0x7ff7b3c403c8
```

You can see that both value of &b and value of a are equal. 

This what happens when we create a pointer variable and point it to another variable.

There's another thing you need to know.

**We can de-reference a pointer**

De-referencing a pointer means accessing the value stored at the memory address pointed to by that pointer

by doing that, we can refer back a pointer and modify the contents of the variable that it points.

```c
#include <stdio.h>

int main()
{
    int b = 42;

    int *a = &b;

    printf("b: %d\n", b); 
    printf("&b: %p\n", &b);
    printf("a: %p\n", a);

    *a = 50;

    printf("b: %d\n", b); 
    printf("&b: %p\n", &b);
    printf("a: %p\n", a);

    return 0;
}
```

In the above code, I have added a few changes from the previous code.

The `*a` here is not telling to change value of a. Instead this tells to go get what `a` is pointing to and use that.

And with the rest of the code in that line, `*a = 50;` tells the program to go get what `a` is pointing to and change the value of it to `50`.

Output of above code will look like follows,

```
b: 42
&b: 0x7ff7b76443c8
a: 0x7ff7b76443c8
b: 50
&b: 0x7ff7b76443c8
a: 0x7ff7b76443c8
```

You'll see that only the value of `b` has changed. The memory addresses stay the same.

This is how de-referencing is done using a pointer. 

**But what's the purpose of this huh?**

01. The `scanf` function

Scanf is a built in function in C that use the advantage of pointers to read values from an input.

Let's see an implementation of it

```c
#include <stdio.h>

int main()
{
    int a, b, c;
    a = b = c = 0;

    printf("Enter 3 numbers:");
    scanf("%d %d %d", &a, &b, &c);
    printf("Result: %d\n", a + b + c);

    return 0;
}
```

In the above code, What `scanf` does is, it's accepting 3 inputs from the user `%d %d %d`(integers) and store them into a, b and c.

You'll notice that we have assigned 0 to all a, b and c.

But if you run this code you'll see that `scanf` somehow modified the variables and provide the output as the addition of all three numbers.

```
Enter 3 numbers:2 5 3
Result: 10
```

So how does `scanf` is able modify the a, b and c?

What `scanf` function does is, it gets the values of `&a, &b, &c` instead of `a, b, c`. 

If you provide `a, b, c` you just giving the values of those variables which are 3 zeros.

By providing the variables as `&a, &b, &c` to the `scanf`, it can point to the addresses of the variables and modify them with the user assigned values.

This is known as a **pass by reference**.

Since this is built in function we don't see what's happening inside the `scanf`.

To get a clear idea, we'll create our own simple pass by reference function.


```c
#include <stdio.h>

void swap(int *a, int *b);

int main(void)
{
    int x, y;
    x = 5;
    y = 10;

    printf("x: %d, y: %d\n", x, y); //before the sawp
    swap(&x, &y);
    printf("x: %d, y: %d\n", x, y); //after the swap

    return 0;
}

void swap(int *a, int *b)
{
    int temp = 0;
    temp = *a;
    *a = *b;
    *b = temp;
}
```

In the above code, we have created a swap function which accepts addresses of variables as `int` pointers.

Simply said, when we pass the `&x` and `&y` to swap function following thing happens first,

`int *a = &x`

`int *b = &y`

Familiar that?

That's what we did before de-referencing in the code where I explained the de-referencing.

After that, inside the swap function, whatever we do with `*a` and `*b` will happen using the values of the variables `x` and `y`.

`temp = *a;` will assign `5` to the variable `temp`

`*a = *b;` will assign `10` to `*a`.

`*b = temp;` will assign `5` to `*b`.

So the final result of the code will display as follows,

```
x: 5, y: 10
x: 10, y: 5
```

First line prints the values before swap and the next line prints the values after swap.

If want to see how memory addresses are de-referred, you can add two more print statements as below in the code.

```c
#include <stdio.h>

void swap(int *a, int *b);

int main(void)
{
    int x, y;
    x = 5;
    y = 10;

    printf("x: %d, y: %d\n", x, y); //before the sawp
    printf("&x: %p\n&y: %p\n", &x, &y); // addresses of x and y
    swap(&x, &y);
    printf("x: %d, y: %d\n", x, y); //after the swap

    return 0;
}

void swap(int *a, int *b)
{
    printf("a: %p\nb: %p\n", a, b); // addresses of x and y
    int temp = 0;
    temp = *a;
    *a = *b;
    *b = temp;
}
```

Newly added print inside the main function prints the memory addresses of `x` and `y`.

Newly added print inside the swap function prints the memory addresses of pointed by `*a` and `*b`.

Output will be shown as below.

```
x: 5, y: 10
&x: 0x7ff7bf5af3c8
&y: 0x7ff7bf5af3c4
a: 0x7ff7bf5af3c8
b: 0x7ff7bf5af3c4
x: 10, y: 5
```

You can see now memory addresses of `x` and `y` matches the memory addresses of `*a` and `*b`.

That means `*a` and `*b` are pointing to `x` and `y`.

So, by using `*a` and `*b`, you can manipulates the values of `x` and `y` inside the swap function without affecting the memory addresses.

This is how a pass by reference works.

There are many cool stuff you can do with pointers in C.

But, I don't want to make this article very lengthy.😊

So, let's see how pointers help the dynamic memory allocation in a future article.☝️😌

Till then, ✌️