What is Pointer to Pointer in C ?
In C programming, a pointer to a pointer, also known as a “double pointer,” is a variable that holds the address of another pointer variable. It is used to create multiple levels of indirection or to indirectly access and modify a pointer variable.
The main purpose of using a pointer to a pointer is to enable dynamic memory allocation and manipulation, especially when dealing with complex data structures like linked lists, trees, or multidimensional arrays. It allows for the modification of a pointer from a different function or context, which can be useful in certain scenarios.
To understand how a pointer to a pointer works, let’s break it down step by step:
1. Declaration: To declare a pointer to a pointer, you need to use the **
notation. Here’s an example:
int **pp;
2 Initialization: After declaring a pointer to a pointer, you can initialize it by assigning the address of another pointer to it. This can be done using the &
operator. Here’s an example:
int *p;
int **pp;
p = &someVariable;
pp = &p;
3. Accessing the value: To access the value stored in the variable pointed to by a pointer to a pointer, you need to use the *
operator twice. Here’s an example:
int value = **pp;
In above example, **pp
dereferences the first pointer to get the second pointer (p
), and then dereferences the second pointer to get the value stored in someVariable
.
4. Modifying the value: To modify the value stored in the variable pointed to by a pointer to a pointer, you also need to use the *
operator twice. Here’s an example:
**pp = newValue;
In above example, **pp
dereferences the first pointer to get the second pointer (p
), and then dereferences the second pointer to modify the value stored in someVariable
to newValue
.
Examples of Pointer to Pointer:
1. Dynamic Memory Allocation:
int **matrix;
int rows = 3;
int cols = 3;
matrix = (int **)malloc(rows * sizeof(int *));
for (int i = 0; i < rows; i++) {
matrix[i] = (int *)malloc(cols * sizeof(int));
}
In above example, we allocate memory for a 2D matrix using a pointer to a pointer. The matrix
variable is a pointer to a pointer that will hold the address of each row in the matrix. By using a double pointer, we can dynamically allocate memory for each row.
2. Swapping Pointers:
void swap(int **ptr1, int **ptr2) {
int *temp = *ptr1;
*ptr1 = *ptr2;
*ptr2 = temp;
}
int main() {
int a = 10;
int b = 20;
int *p1 = &a;
int *p2 = &b;
swap(&p1, &p2);
// Now p1 points to 20 and p2 points to 10
return 0;
}
In above example, the swap
function takes two pointers to pointers as arguments. Inside the function, the addresses stored in the pointers are swapped using a temporary pointer variable. This allows us to swap the values that the pointers point to.
3. Linked List Manipulation:
struct Node {
int data;
struct Node *next;
};
void insert(struct Node **head, int data) {
struct Node *newNode = (struct Node *)malloc(sizeof(struct Node));
newNode->data = data;
newNode->next = *head;
*head = newNode;
}
int main() {
struct Node *list = NULL;
insert(&list, 10);
insert(&list, 20);
// Now list points to the first node of the linked list
return 0;
}
In above example, we have a linked list implementation. The insert
function takes a pointer to a pointer to the head of the list. By passing the address of the list
pointer (&list
), we can modify the head pointer of the list and insert new nodes at the beginning.