C Multidimensional Pointer
In this page:
Pointers to Pointers
A pointer to a pointer stores the address of another pointer variable rather than the address of ordinary data, and is declared in C with two asterisks, like int **pp;. This extra layer of indirection is what lets you modify a pointer's own value (not just the data it points to) from inside another function.
Example: Pointers to Pointers
#include <stdio.h>
int main() {
int x = 5;
int *p = &x;
int **pp = &p;
printf("%d", **pp);
return 0;
}
Login to try C/C++/Java/PHP code in the editor
Pointer to an Array
A pointer to an array can hold the address of an entire row of a 2D array at once, rather than pointing at a single element, which lets you pass whole rows into functions without copying their contents. Declaring the parameter type correctly (matching the row's fixed inner dimension) is what makes this kind of pointer arithmetic safe.
Example: Pointer to an Array
#include <stdio.h>
int main() {
int grid[2][3] = {{1,2,3},{4,5,6}};
int (*rowPtr)[3] = grid;
printf("%d", rowPtr[1][2]);
return 0;
}
Login to try C/C++/Java/PHP code in the editor
Dynamically Allocating 2D Arrays
To build a 2D array dynamically, first allocate an array of pointers to represent each row, then allocate a separate block of memory for each individual row and store its address in the corresponding pointer slot. This two-step allocation is what lets each row have a size decided at runtime, unlike a fixed-size 2D array.
Example: Dynamically Allocating 2D Arrays
#include <stdio.h>
#include <stdlib.h>
int main() {
int rows = 2, cols = 2;
int **arr = malloc(rows * sizeof(int*));
for (int i = 0; i < rows; i++) {
arr[i] = malloc(cols * sizeof(int));
}
arr[0][0] = 5;
printf("%d", arr[0][0]);
for (int i = 0; i < rows; i++) free(arr[i]);
free(arr);
return 0;
}
Login to try C/C++/Java/PHP code in the editor
Accessing 2D Array with Pointers
Because a 2D array's elements sit contiguously in memory, the expression *(*(arr + i) + j) computes the exact same address as the more familiar arr[i][j] — both walk to row i, then j elements further into that row. Understanding this equivalence is what makes raw pointer traversal of matrices possible.
Example: Accessing 2D Array with Pointers
#include <stdio.h>
int main() {
int arr[2][2] = {{1,2},{3,4}};
printf("%d", *(*(arr + 1) + 0));
return 0;
}
Login to try C/C++/Java/PHP code in the editor
Freeing Dynamic 2D Arrays
When freeing a dynamically allocated 2D array, you must free each individually allocated row before freeing the array of row pointers itself, and doing it in the opposite order leaves the row memory permanently leaked since you'd lose the only pointers that referenced it. Always free from the inside out.
Example: Freeing Dynamic 2D Arrays
#include <stdio.h>
#include <stdlib.h>
int main() {
int rows = 2;
int **arr = malloc(rows * sizeof(int*));
for (int i = 0; i < rows; i++) {
arr[i] = malloc(2 * sizeof(int));
}
for (int i = 0; i < rows; i++) free(arr[i]);
free(arr);
printf("Freed rows first, then the row array");
return 0;
}
Login to try C/C++/Java/PHP code in the editor
Chapter Quiz — Complete all 20 topics to unlock
0/20 topics done
Complete these topics first:
- C typedef
- C Type Casting
- C Bit Fields
- C Variable Length Arrays
- C Command Line Arguments
- C Function Pointers
- C Callback Functions
- C Multidimensional Pointer
- C string.h Functions
- C stdlib.h Functions
- C math.h Functions
- C time.h Functions
- C ctype.h Functions
- C errno.h
- C assert.h
- C Error Handling
- C Debugging Techniques
- C Code Style & Best Practices
- C Common Mistakes
- C Interview Questions