As we know, pointers are used in C language to store the addresses of variables. Pointers can reduce the time to access variables. However, in C language, we can also define a pointer to store the address of another pointer. Such a pointer is called a double pointer (pointer to a pointer). The first pointer is used to store the address of a variable, while the second pointer is used to store the address of the first pointer. Let’s understand this through the illustration below.

Syntax
The syntax for declaring a double pointer is as follows:
int **p; // Pointer to a pointer to an integer
Consider the following example:
#include <stdio.h>
void main(){ int a = 10; int *p; int **pp; p = &a; // Pointer p points to the address of variable a pp = &p; // Double pointer pp points to the address of pointer p printf("Address of a: %x\n", &a); // Output address of a printf("Address of p: %x\n", p); // Output address of p printf("Value stored by pointer p: %d\n", *p); // Output value stored by pointer p, which is the value of a printf("Address of pp: %x\n", pp); // Output address of pp printf("Value stored by pointer pp: %d\n", **pp); // Output value stored by pointer pp, which is the value of a}
Output
Address of a: d26a8734Address of p: d26a8738Value stored by pointer p: 10Address of pp: d26a8738Value stored by pointer pp: 10
👇 Click to Claim 👇
👉 C Language Knowledge Resource Collection
Example of Double Pointers in C
Let’s look at an example where one pointer points to the address of another pointer.

As shown in the figure above, p2 contains the address of p (fff2), and p contains the address of the variable number (fff4).
#include <stdio.h>
int main() { int number = 50; int *p; // Pointer to an integer int **p2; // Pointer to a pointer
p = &number; // Store the address of variable number p2 = &p;
printf("Address of variable number is %x \n", &number); printf("Address of variable p is %x \n", p); printf("Value of variable p is %d \n", *p); printf("Address of variable p2 is %x \n", p2); printf("Value pointed by p2 is %d \n", **p2);
return 0;}
Here is the C language tutorial translated for you, with the code displayed in code blocks:
#include <stdio.h>
int main() { int number = 50; int *p; // Pointer to an integer int **p2; // Pointer to a pointer
p = &number; // Store the address of variable number p2 = &p;
printf("Address of variable number is %x \n", &number); printf("Address of variable p is %x \n", p); printf("Value of variable p is %d \n", *p); printf("Address of variable p2 is %x \n", p2); printf("Value pointed by p2 is %d \n", **p2);
return 0;}
Output
Address of variable number is fff4Address of variable p is fff4Value of variable p is 50Address of variable p2 is fff2Value pointed by p2 is 50
Question: What is the output of the following program?
#include <stdio.h>
int main(){ int a[10] = {100, 206, 300, 409, 509, 601}; // Line 1 int *p[] = {a, a+1, a+2, a+3, a+4, a+5}; // Line 2 int **pp = p; // Line 3
pp++; // Line 4 printf("%d %d %d\n", pp - p, *pp - a, **pp); // Line 5
*pp++; // Line 6 printf("%d %d %d\n", pp - p, *pp - a, **pp); // Line 7
++*pp; // Line 8 printf("%d %d %d\n", pp - p, *pp - a, **pp); // Line 9
++**pp; // Line 10 printf("%d %d %d\n", pp - p, *pp - a, **pp); // Line 11
return 0;}
Explanation

In the above question, double pointers are used for pointer arithmetic. An integer array a with 6 elements is defined, pointed to by the pointer array p. The pointer array p is pointed to by the double pointer pp. However, the above image provides a brief concept of how memory is allocated for array a and pointer array p. Elements of p are pointers to each element of array a. Since we know that the array name contains the base address of the array, we can traverse the values of the array using (a), (a+1), etc. As shown in the figure, a[0] can be accessed in the following ways:
-
a[0]: This is the simplest way to access the first element of the array.
-
*(a): Since a stores the address of the first element of the array, we can access its value through indirect pointer access.
-
p[0]: If we want to access a[0] through pointer p, we can use the indirect operator () on the first element of pointer array p, i.e., *p[0].
-
(pp): Since pp stores the base address of the pointer array, *pp will give the value of the first element of the pointer array, which is the address of the first element of the integer array. pp will give the actual value of the first element of the integer array.
Next, let’s discuss the program. Lines 1 and 2 declare an integer array and a pointer array, respectively. Line 3 initializes the double pointer to the pointer array p. As shown in the figure, if the address of the array starts from 200, and the size of an integer is 2, the values of the pointer array will be 200, 202, 204, 206, 208, 210. Assuming the base address of the pointer array is 300, the double pointer pp contains the address of the pointer array, which is 300. Line 4 increments the value of pp by 1, so pp now points to address 302.Line 5 contains an expression that prints three values, pp – p, *pp – a, **pp. Let’s calculate each value.
-
pp = 302, p = 300 => pp – p = (302-300)/2 => pp – p = 1, which prints 1.
-
pp = 302, *pp = 202, a = 200 => *pp – a = 202 – 200 = 2/2 = 1, which prints 1.
-
pp = 302, pp = 202, (*pp) = 206, which prints 206.
Thus, as a result of line 5, the console will print 1, 1, 206. Line 6 writes pp++. Here we must note that the two unary operators and ++ have the same priority. Therefore, according to the rules of associativity, it will be evaluated from right to left. Thus, the expression pp++ can be rewritten as ((pp++)). Since pp = 302, it now becomes 304. *pp will give 204.
Line 7 again writes an expression that prints three values, pp – p, pp – a, pp. Let’s calculate each value.
-
pp = 304, p = 300 => pp – p = (304 – 300)/2 => pp – p = 2, which prints 2.
-
pp = 304, *pp = 204, a = 200 => *pp – a = (204 – 200)/2 = 2, which prints 2.
-
pp = 304, pp = 204, (*pp) = 300, which prints 300.
Thus, as a result of line 7, the console will print 2, 2, 300. Line 8 writes ++pp. According to the rules of associativity, this can be rewritten as (++((pp))). Since pp = 304, pp = 204, pp = *(p[2]) = 206, it will now point to a[3].
Line 9 again writes an expression that prints three values, pp – p, pp – a, pp. Let’s calculate each value.
-
pp = 304, p = 300 => pp – p = (304 – 300)/2 => pp – p = 2, which prints 2.
-
pp = 304, *pp = 206, a = 200 => *pp – a = (206 – 200)/2 = 3, which prints 3.
-
pp = 304, pp = 206, (*pp) = 409, which prints 409.
Thus, as a result of line 9, the console will print 2, 3, 409. Line 10 writes ++pp. According to the rules of associativity, this can be rewritten as (++(((pp)))). pp = 304, *pp = 206, pp = 409, ++**pp => *pp = *pp + 1 = 410. In other words, a[3] = 410.
Line 11 again writes an expression that prints three values, pp – p, pp – a, pp. Let’s calculate each value.
-
pp = 304, p = 300 => pp – p = (304 – 300)/2 => pp – p = 2, which prints 2.
-
pp = 304, *pp = 206, a = 200 => *pp – a = (206 – 200)/2 = 3, which prints 3.
-
In line 8, **pp = 410.
Thus, as a result of line 11, the console will print 2, 3, 410.
Output
1 1 2062 2 3002 3 4092 3 410
Programmer Technical Exchange Group
Scan the QR code to join the group, remember to note: city, nickname, and technical direction.