Back to: C Tutorials For Beginners and Professionals
Pointer to Pointer in C Language with Examples
In this article, I will discuss Pointer to Pointer in C Language with Examples. Please read our previous articles discussing Arithmetic Operations on Pointers in C Language with Examples. In C programming, a pointer to a pointer is a form of multiple indirection or a chain of pointers. Normally, a pointer stores the address of a variable. Similarly, a pointer to a pointer is a variable that stores the address of another pointer.
Pointer to Pointer (Double Pointer) in C Language:
It is a concept of holding the pointer address into another pointer variable. In C Language, a pointer variable points to a location in memory and is used to store the address of a variable. In C, we can also define a pointer to store the address of another pointer. Such a pointer is called a double pointer (pointer to pointer). So, when we define a pointer to a pointer, the first pointer is used to store the address of the variable, and the second pointer is used to store the address of the first pointer. This is the reason why they are also called double-pointers.
In C programming language, the pointer-to-pointer relations can be applied up to 12 stages, but generally, there are no limitations. For a pointer variable, we can apply 12 indirection operators. When we are using the pointer-to-pointer relations, then performance will be decreased.
How to Declare a Pointer to Pointer in C?
Declaring a Pointer to a Pointer or double-pointer is similar to declaring a pointer in C. The difference is we have to place an additional * before the pointer’s name.
Syntax: int **ptr;
Understanding Pointer to Pointer in C
Consider a regular pointer:
int x = 10;
int *p = &x; // ‘p’ is a pointer to ‘x’
Here, p is a pointer that holds the address of x. Now, let’s introduce a pointer to a pointer:
int **pp = &p; // pp is a pointer to p, which is a pointer to x
Here, pp is a pointer to a pointer. It holds the address of p, which in turn holds the address of x.
Dereferencing a Pointer to Pointer
Dereferencing a pointer to a pointer involves an extra level of indirection:
- *pp dereferences pp to get p.
- **pp dereferences pp to get p, and then again dereferences p to get the value of x.
Example:
Here’s a simple example demonstrating the use of a pointer to a pointer:
#include <stdio.h> int main() { int value = 5; int *ptr = &value; // Pointer to an int int **ptrToPtr = &ptr; // Pointer to a pointer to an int printf("Value = %d\n", value); printf("Value via ptr = %d\n", *ptr); printf("Value via ptrToPtr = %d\n", **ptrToPtr); return 0; }
Example to understand Pointer to Pointer in C:
#include<stdio.h> void main () { int a = 10; int *p; int **pp; p = &a; // pointer p is pointing to the address of a pp = &p; // pointer pp is a double pointer pointing to the address of pointer p printf("address of a: %x\n",p); // Address of a will be printed printf("address of p: %x\n",pp); // Address of p will be printed printf("value stored at p: %d\n",*p); // value stoted at the address contained by p i.e. 10 will be printed printf("value stored at pp: %d\n",**pp); // value stored at the address contained by the pointer stoyred at pp }
Output:
Example: Pointer to Pointer in C Language
#include<stdio.h> int main () { int i = 10; int *ptr; int **pptr; int ***ppptr; ptr = &i; pptr = &ptr; ppptr = &pptr; printf ("\n %d %d %d %d", i, *ptr, **pptr, ***ppptr); }
Output: 10 10 10 10
For a better understanding of the above program, please have a look at the following diagram.
How the logic is evaluated in the above Program:
Use Cases for Pointers to Pointers in C Language:
- Dynamic Memory Allocation: In functions that dynamically allocate memory and need to return a pointer to this memory, a pointer to a pointer can be used.
- Modifying a Pointer in a Function: To modify a pointer itself in a function (not the value it points to), you must pass it to that pointer.
- Arrays of Strings: An array of strings can be represented as an array of pointers to characters. If you want to manipulate this array (like reallocating it), a pointer to a pointer is used.
- Implementing Data Structures: In complex data structures like trees or linked lists, pointers to pointers can be used to handle nodes effectively.
- Function Pointers Array: For an array of function pointers, if the functions themselves take pointers as arguments, you might end up with pointers to pointers.
Example: Basic Usage of Pointer to Pointer
#include <stdio.h> int main() { int var = 789; // An integer variable int *ptr = &var; // A pointer to the integer variable 'var' int **pptr = &ptr; // A pointer to the pointer 'ptr' printf("Value of var = %d\n", var); printf("Value available at *ptr = %d\n", *ptr); printf("Value available at **pptr = %d\n", **pptr); return 0; }
In this example, var is a normal integer variable, ptr is a pointer that holds the address of var, and pptr is a pointer to ptr, i.e., it holds the address of ptr. The **pptr expression allows us to access the value of var.
Example: Modifying Values
#include <stdio.h> void addOne(int **ptr) { ++(**ptr); } int main() { int value = 10; int *ptr = &value; printf("Before: %d\n", value); addOne(&ptr); // Pass the address of the pointer to the function printf("After: %d\n", value); return 0; }
In this example, the function addOne is designed to take a pointer to a pointer to an integer. It dereferences it twice to increment the value of the actual integer value.
Example: Arrays of Strings
#include <stdio.h> int main() { char *names[] = { "Alice", "Bob", "Charlie" }; int i; for (i = 0; i < 3; i++) { printf("Name[%d] = %s\n", i, names[i]); } return 0; }
Here, names is an array of pointers to char. Each element in names points to the first character of a string.
Example: Dynamic Memory Allocation
#include <stdio.h> #include <stdlib.h> int main() { int **arr; int rows = 2, cols = 3, i, j; // Allocate memory for rows arr = (int **)malloc(rows * sizeof(int *)); // Allocate memory for columns for (i = 0; i < rows; i++) { arr[i] = (int *)malloc(cols * sizeof(int)); } // Assign values and print them for (i = 0; i < rows; i++) { for (j = 0; j < cols; j++) { arr[i][j] = i + j; printf("%d ", arr[i][j]); } printf("\n"); } // Free the allocated memory for (i = 0; i < rows; i++) { free(arr[i]); } free(arr); return 0; }
In this final example, arr is a pointer to a pointer used to create a 2D dynamic array. Memory is allocated for each row and column, and then it is freed at the end of the program to avoid memory leaks.
Key Points:
- Pointer to pointer adds an additional level of indirection, making it more complex, but is is also powerful.
- It’s commonly used for dynamic memory allocation, handling multiple strings, and in complex data structures.
- Care should be taken to manage memory effectively to avoid leaks.
In the next article, I will discuss Pointer to an Array of Functions in C language. In this article, I try to explain Pointer to Pointer in C Language with Examples. I hope you enjoy this Pointer to Pointer in C Language with Examples article. I would like to have your feedback. Please post your feedback, questions, or comments about this article.