← Back to C Course | Chapter 7: Pointers | Lesson 9 of 9

C Pointer to Pointer

A pointer to a pointer is a note that tells you where another note is stored, and that note tells you where the real thing is. You follow it one step at a time.
Syntax
c
data_type **pointer_to_pointer = &pointer_name;

**pointer_to_pointer;

What is a Pointer to a Pointer?

This chain is exactly the mechanism argv uses in main(int argc, char **argv) -- argv is a pointer to an array of pointers, where each element points to one command-line argument string.

Example: What is a Pointer to a Pointer?

c
// Include standard input/output (printf, scanf)
#include <stdio.h>
// Program execution starts in main()
int main() {
	char *args[2] = {"prog", "arg1"};
	char **argv = args;
	// Print formatted text to the screen
	printf("%s", argv[1]);
	// Return 0 to signal that the program finished successfully
	return 0;
}

Declaring and Initializing

The declaration mirrors the double-pointer syntax you'd use for any type: int **pptr for pointers to int pointers, char **names for arrays of string pointers, and so on -- the type before the asterisks must match what's ultimately being pointed to.

Example: Declaring and Initializing

c
// Include standard input/output (printf, scanf)
#include <stdio.h>
// Program execution starts in main()
int main() {
	// Declare x and set it to 5
	int x = 5;
	int *ptr = &x;
	int **pptr = &ptr;
	// Print formatted text to the screen
	printf("%d", **pptr);
	// Return 0 to signal that the program finished successfully
	return 0;
}

Dereferencing Once

This gives you an intermediate address in the chain -- if pptr points to ptr, then *pptr gives you ptr's value, which is itself an address (the one ptr points to), not yet the final data.

Example: Dereferencing Once

c
// Include standard input/output (printf, scanf)
#include <stdio.h>
// Program execution starts in main()
int main() {
	// Declare x and set it to 5
	int x = 5;
	int *ptr = &x;
	int **pptr = &ptr;
	// Print formatted text to the screen
	printf("%p", (void*)*pptr);
	// Return 0 to signal that the program finished successfully
	return 0;
}

Dereferencing Twice

This is the operation that finally reaches the actual stored data at the bottom of the indirection chain, skipping past both layers of pointer addresses to get to the real value.

Example: Dereferencing Twice

c
// Include standard input/output (printf, scanf)
#include <stdio.h>
// Program execution starts in main()
int main() {
	// Declare x and set it to 5
	int x = 5;
	int *ptr = &x;
	int **pptr = &ptr;
	// Print formatted text to the screen
	printf("%d", **pptr);
	// Return 0 to signal that the program finished successfully
	return 0;
}

Modifying Pointers in Functions

This pattern is common in functions that allocate memory and need to hand the new address back to the caller through a parameter, since a single pointer parameter would only let you modify a copy of the caller's pointer, not the original.

Example: Modifying Pointers in Functions

c
// Include standard input/output (printf, scanf)
#include <stdio.h>
void allocate(int **out) {
	static int value = 10;
	*out = &value;
}
// Program execution starts in main()
int main() {
	int *ptr = NULL;
	allocate(&ptr);
	// Print formatted text to the screen
	printf("%d", *ptr);
	// Return 0 to signal that the program finished successfully
	return 0;
}
Related Topics
{# common_mistakes/chapter_summary/browser_support: on Hindi pages the view already swaps in the hi_ translation fields (or blanks these out if untranslated), so this renders correctly for both languages without a lang_code check here. #}
Common Mistakes
  1. Dereferencing only once and treating *pp as the value, when it is still a pointer.
  2. Using a pointer to a pointer before assigning it a valid address.
  3. Losing track of levels, for example passing &p where p is expected, which gives a type mismatch.
Chapter Summary
  • A pointer stores a memory address, and pointer arithmetic moves through memory one element at a time.
  • Pointers connect closely to arrays and functions, letting functions work directly with the caller's data.
  • Null, void, and double pointers cover special cases, such as empty pointers, generic pointers, and pointers to pointers.

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.