C language content
Pointers to pointers in C can be a bit tricky to grasp initially, but they are very powerful once you understand them. To fully understand pointers to pointers, we first need to review some basics of pointers and then expand that understanding to multiple levels of indirection.

Basics of Pointers

A pointer in C is a variable that stores the memory address of another variable. For example, if we have an integer variable int x = 10;, we can create a pointer to x like this:

				
					int x = 10;
int *p = &x;

				
			

Here, p is a pointer to an integer, and it stores the address of x.

Pointer to a Pointer

A pointer to a pointer is a variable that stores the address of another pointer. This means it is a pointer that points to another pointer, which in turn points to the actual data.

Let’s break this down step by step with an example.

Step 1: Define a Pointer to an Integer

First, define an integer variable and a pointer to that integer:

				
					int x = 10;
int *p = &x;

				
			

Here, p is a pointer to x.

Step 2: Define a Pointer to a Pointer

Next, define a pointer to the pointer p:

				
					int **pp = &p;

				
			

Here, pp is a pointer to p, which in turn is a pointer to x. So, pp is a pointer to a pointer to an integer.

Memory Layout

To visualize this, let’s see how these variables are stored in memory:

				
					+----+        +----+        +----+
| x  | <----- | p  | <----- | pp |
+----+        +----+        +----+

				
			
  • x contains the value 10.
  • p contains the address of x.
  • pp contains the address of p.

Accessing Values

To access the value of x using these pointers, you can use the following syntax:

  • *p gives you the value of x (which is 10).
  • **pp also gives you the value of x (which is 10).

Here’s a complete example demonstrating pointers to pointers:

				
					#include <stdio.h>

int main() {
    int x = 10;    // A normal integer variable
    int *p = &x;   // A pointer to an integer
    int **pp = &p; // A pointer to a pointer to an integer

    printf("Value of x: %d\n", x);         // 10
    printf("Value pointed to by p: %d\n", *p);    // 10
    printf("Value pointed to by pp: %d\n", **pp); // 10

    printf("Address of x: %p\n", (void*)&x);    // Address of x
    printf("Address stored in p: %p\n", (void*)p);    // Address of x
    printf("Address stored in pp: %p\n", (void*)pp);  // Address of p
    printf("Address of p: %p\n", (void*)&p);    // Address of p
    printf("Address of pp: %p\n", (void*)&pp);  // Address of pp

    return 0;
}

				
			

Why Use Pointers to Pointers?

Pointers to pointers are useful in several scenarios, such as:

  1. Dynamic Memory Allocation:
    • When dealing with dynamically allocated multidimensional arrays, pointers to pointers are often used.
    • For example, dynamically allocating a 2D array:
				
					int rows = 3, cols = 4;
int **array = malloc(rows * sizeof(int *));
for(int i = 0; i < rows; i++) {
    array[i] = malloc(cols * sizeof(int));
}

				
			

2. Function Parameters:

  • If you need a function to modify the value of a pointer, you pass a pointer to that pointer.
				
					void allocateMemory(int **ptr) {
    *ptr = malloc(sizeof(int));
    **ptr = 10;
}

int main() {
    int *p = NULL;
    allocateMemory(&p);
    printf("Value pointed to by p: %d\n", *p); // 10
    free(p);
    return 0;
}

				
			

Summary

Pointers to pointers add an extra layer of indirection, making it possible to handle more complex data structures and scenarios in C. They allow you to dynamically allocate multi-dimensional arrays, modify pointers within functions, and create more flexible and powerful data handling mechanisms. Understanding how to use them effectively requires practice and a solid grasp of the basics of pointers.

Scroll to Top