Question
In C, how many pointer indirections (*) are allowed for a single variable declaration?
For example:
int a = 10;
int *p = &a;
int **q = &p;
int ***r = &q;
This pattern can continue with more levels of indirection, such as:
int ****************zz;
Is there a defined limit on how many pointer levels are allowed in C, and what determines that limit?
Short Answer
By the end of this page, you will understand what pointer levels mean in C, how multi-level pointers are declared and used, whether the language defines a maximum depth, and what practical limits exist in real programs and compilers.
Concept
A pointer in C stores the memory address of another object. When you add another *, you create a pointer to a pointer.
int *pmeansppoints to anintint **qmeansqpoints to a pointer that points to anintint ***rmeansrpoints to a pointer that points to a pointer that points to anint
Each extra * adds one more level of indirection.
This matters because C often works directly with memory addresses. Multi-level pointers are useful when:
- you need a function to modify a pointer variable
- you work with dynamically allocated arrays of pointers
- you represent nested structures such as command-line argument lists or strings
Is there a maximum in C?
The C language does not set a small practical number like 2, 3, or 10. In principle, you can keep adding pointer levels as long as the declaration is valid and your compiler can handle it.
However, in practice, limits come from:
- the compiler's implementation limits
- parser complexity
- readability and maintainability
- whether the type is actually useful
Mental Model
Think of a pointer like a note that tells you where something is stored.
- A normal variable is the actual item
- A pointer is a note with the item's location
- A pointer to a pointer is a note that tells you where the first note is
- A pointer to a pointer to a pointer is a note that tells you where the second note is
So each * means: follow one more layer of notes.
Example:
ais the real box containing10pis a note pointing toaqis a note pointing topris a note pointing toq
To get the value 10 from r, you must follow three notes:
***r
The more stars you add, the more times you need to follow references to reach the actual value.
Syntax and Examples
The basic syntax is:
type *name;
type **name;
type ***name;
Example:
#include <stdio.h>
int main(void) {
int a = 10;
int *p = &a;
int **q = &p;
int ***r = &q;
printf("a = %d\n", a);
printf("*p = %d\n", *p);
printf("**q = %d\n", **q);
printf("***r = %d\n", ***r);
return 0;
}
Output:
a = 10
*p = 10
**q = 10
***r = 10
What each line means
int *p = &a;stores the address ofaint **q = &p;stores the address ofp
Step by Step Execution
Trace this example:
#include <stdio.h>
int main(void) {
int a = 10;
int *p = &a;
int **q = &p;
printf("%d\n", **q);
return 0;
}
Step 1
int a = 10;
A variable a is created and stores the value 10.
Step 2
int *p = &a;
p stores the address of a.
If a lives at some memory location, p contains that location.
Step 3
**q = &p;
Real World Use Cases
Multi-level pointers are uncommon in beginner code, but they are useful in real C programs.
1. Letting a function modify a pointer
If a function needs to change a pointer variable itself, you pass a pointer to that pointer.
#include <stdlib.h>
void allocate_int(int **ptr) {
*ptr = malloc(sizeof(int));
if (*ptr != NULL) {
**ptr = 42;
}
}
Here int **ptr lets the function assign a new address to the caller's pointer.
2. Arrays of strings
Command-line arguments are commonly represented as char **argv.
int main(int argc, char **argv) {
return 0;
}
argv is effectively a pointer to pointers to characters, because each argument is a string.
3. Dynamic 2D data structures
A dynamically allocated array of row pointers may use .
Real Codebase Usage
In real codebases, developers usually keep pointer depth low and use extra levels only when they solve a specific problem.
Common patterns
Guard clauses
When using multi-level pointers, code often checks for NULL early.
if (ptr == NULL || *ptr == NULL) {
return;
}
This prevents invalid dereferencing.
Output parameters
Functions often use T **out to allocate memory or return a newly created object.
int create_buffer(char **out) {
*out = malloc(100);
if (*out == NULL) {
return -1;
}
return 0;
}
Validation before dereferencing
Each pointer level may need validation.
if (q != NULL && *q != NULL) {
printf("%d\n", **q);
}
Common Mistakes
1. Confusing declaration with dereference
This declares a pointer:
int *p;
This dereferences a pointer:
*p = 10;
The * symbol is used in both contexts, but the meaning depends on where it appears.
2. Using the wrong number of stars
Broken code:
int a = 10;
int *p = &a;
int *q = &p;
Problem:
&pis of typeint **- but
qis declared asint *
Correct version:
int a = 10;
int *p = &a;
int **q = &p;
3. Dereferencing too many or too few times
Broken code:
Comparisons
| Concept | Meaning | Typical use | Common depth |
|---|---|---|---|
int | Stores an integer value | Regular numeric data | 0 |
int * | Points to an integer | Pass-by-reference, dynamic memory | 1 |
int ** | Points to a pointer to an integer | Modify a pointer in a function, 2D structures | 2 |
int *** | Points to a pointer to a pointer | Rare, nested ownership or APIs | 3 |
Pointer depth vs array syntax
These can look related but mean different things:
*p;
arr[];
Cheat Sheet
Quick reference
Declarations
int a;
int *p;
int **q;
int ***r;
Meaning
int-> valueint *-> address of anintint **-> address of anint *int ***-> address of anint **
Example chain
int a = 10;
int *p = &a;
int **q = &p;
int ***r = &q;
Accessing the final value
*p // 10
**q // 10
***r // 10
Main rule
Each * means one more level of indirection.
Is there a language limit?
FAQ
How many levels of pointers are allowed in C?
C does not define a small fixed number like 5 or 10. You can declare many levels of pointers, but the practical limit depends on the compiler.
Is int ********p; valid C?
Yes, if the declaration is syntactically correct and the compiler supports it.
Why would anyone use a double pointer in C?
A double pointer is commonly used when a function needs to modify a pointer variable, such as allocating memory and storing the result in the caller's pointer.
Are triple pointers used in real programs?
Yes, but rarely. They appear in some APIs, nested data structures, and advanced memory-handling code.
Does more pointer depth use more memory?
A pointer variable uses memory for storing an address. More separate pointer variables mean more memory usage, but the number of * in a type is mainly about type relationships, not automatic extra storage layers.
Is there any benefit to using very deep pointers?
Usually no. Deep pointer chains are hard to read and maintain. They are only helpful when the problem truly requires multiple levels of indirection.
What is the difference between * in a declaration and * in an expression?
In a declaration, * means "this variable is a pointer." In an expression, * means "dereference this pointer to access what it points to."
Mini Project
Description
Build a small C program that demonstrates one, two, and three levels of pointers by printing both values and addresses. This helps you see how each pointer layer refers to the previous one and when dereferencing is needed.
Goal
Create a program that declares int, int *, int **, and int ***, then prints the stored value through each valid dereference level.
Requirements
- Declare an integer variable with an initial value.
- Create a single pointer, double pointer, and triple pointer linked correctly.
- Print the integer value directly and through each pointer chain.
- Print at least one address using
%p. - Keep the program valid and compilable in standard C.
Keep learning
Related questions
Array-to-Pointer Conversion in C and C++ Explained
Learn what array-to-pointer conversion means in C and C++, how array decay works, and how it differs from a pointer to an array.
Building More Fault-Tolerant Embedded C++ Applications for Radiation-Prone ARM Systems
Learn practical C++ and compile-time techniques to reduce soft-error damage in embedded ARM systems exposed to radiation.
C Pointer to Array vs Array of Pointers: How to Read Complex Declarations
Learn the difference between pointer-to-array and array-of-pointers in C, plus a simple rule for reading complex declarations correctly.