Pointers to pointers, also known as double pointers, are a concept in C where a pointer variable holds the memory address of another pointer variable. This allows for indirect access to a memory location and is particularly useful in scenarios where you need to modify the value of a pointer itself or pass a pointer to a function by reference.
int* my_array[10]; // An array of pointers to integers
int** my_double_pointer = my_array; // A double pointer to the array of pointers
The double pointer my_double_pointer stores the address of the first element of the array my_array. This means that we can use the double pointer to access any element of the array by dereferencing it twice.
int value = *(*my_double_pointer + 5); // Get the value of the 6th element of the array
#include <stdio.h>
int main() {
int x = 10;
int *ptr1 = &x; // Pointer to an integer
int **ptr2 = &ptr1; // Pointer to a pointer to an integer
printf("Value of x: %d\n", x);
printf("Value pointed to by ptr1: %d\n", *ptr1);
printf("Value pointed to by ptr2: %d\n", **ptr2);
return 0;
}
//Output:
Value of x: 10
Value pointed to by ptr1: 10
Value pointed to by ptr2: 10
In this example, ptr1 is a pointer to an integer (int *), and ptr2 is a pointer to a pointer to an integer (int **). ptr2 holds the address of ptr1, and using **ptr2, we can indirectly access and modify the value of x.
Passing Pointers to Functions
#include <stdio.h>
void modifyValue(int **ptr) {
**ptr = 20;
}
int main() {
int x = 10;
int *ptr1 = &x;
printf("Value of x before function call: %d\n", x);
modifyValue(&ptr1); // Pass a pointer to pointer
printf("Value of x after function call: %d\n", x);
return 0;
}
//Output:
Value of x before function call: 10
Value of x after function call: 20
In this example, the modifyValue function takes a pointer to a pointer as an argument. By passing the address of ptr1 to this function, we can modify the value of x indirectly through **ptr.
Dynamic Memory Allocation
#include <stdio.h>
#include <stdlib.h>
int main() {
int **matrix;
int rows = 3;
int cols = 4;
// Allocate memory for a 2D array using double pointers
matrix = (int **)malloc(rows * sizeof(int *));
for (int i = 0; i < rows; i++) {
matrix[i] = (int *)malloc(cols * sizeof(int));
}
// Assign values to the elements
matrix[1][2] = 42;
// Deallocate memory
for (int i = 0; i < rows; i++) {
free(matrix[i]);
}
free(matrix);
return 0;
}
In this example, we use double pointers to dynamically allocate memory for a 2D array. The matrix variable is of type int **, and we allocate memory for both rows and columns dynamically. Double pointers make it possible to create and manage dynamic multi-dimensional arrays.
Double pointer to create a linked list
The following code shows how to use a double pointer to create a linked list:
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node* next;
};
struct node* head = NULL; // A single pointer to the head of the linked list
void add_node(int data) {
struct node* new_node = malloc(sizeof(struct node));
new_node->data = data;
new_node->next = NULL;
if (head == NULL) {
head = new_node; // Assign the new_node directly to head
} else {
struct node* current = head;
while (current->next != NULL) {
current = current->next;
}
current->next = new_node; // Update the current node's next to point to new_node
}
}
void print_list() {
struct node* current = head;
while (current != NULL) {
printf("%d\n", current->data);
current = current->next;
}
}
int main() {
add_node(10);
add_node(20);
add_node(30);
print_list();
return 0;
}
//Output:
10
20
30
Conclusion
Pointers to pointers are a powerful concept in C, allowing for more advanced memory management, dynamic data structures, and passing pointers by reference to functions. They are essential in scenarios where you need to work with pointers in a flexible and indirect manner.