Question
C Pointer to Array vs Array of Pointers: How to Read Complex Declarations
Question
What is the difference between the following C declarations?
int *arr1[8];
int (*arr2)[8];
int *(arr3[8]);
Also, what is the general rule for understanding more complex C declarations?
Short Answer
By the end of this page, you will understand how to tell apart an array of pointers from a pointer to an array in C. You will also learn a reliable rule for reading complex C declarations, so syntax like int *arr1[8] or int (*arr2)[8] becomes much easier to decode.
Concept
C declarations can look confusing because symbols like *, [], and () combine in ways that change meaning.
The key idea is that arrays and pointers are different types, even though they are often related.
Consider these declarations:
int *arr1[8];
int (*arr2)[8];
int *(arr3[8]);
What each one means
int *arr1[8];
arr1 is an array of 8 elements, where each element is a pointer to int.
arr1[0]is anint *arr1[1]is anint *- and so on
int (*arr2)[8];
arr2 is a pointer to an array of 8 integers.
Mental Model
Think of C declarations like reading a road sign from the variable name outward.
Start at the variable name, then look:
- to the right first if possible
- then to the left
- use parentheses as barriers that group things together
Analogy
Imagine the variable name is a person in the middle of a maze.
- If the first thing they touch is
[], they are an array. - If the first thing they touch is
*, they are a pointer. - Parentheses can change which path they must take first.
For example:
int *arr1[8];
Start at arr1:
- right:
[8]→arr1is an array of 8 - left:
*→ whose elements are pointers - base type:
int
So: array of 8 pointers to int.
Now:
int (*arr2)[8];
Start at :
Syntax and Examples
Core syntax
int *a[8]; // array of 8 pointers to int
int (*b)[8]; // pointer to array of 8 int
Example 1: Array of pointers
#include <stdio.h>
int main(void) {
int x = 10, y = 20, z = 30;
int *arr[3] = { &x, &y, &z };
printf("%d\n", *arr[0]);
printf("%d\n", *arr[1]);
printf("%d\n", *arr[2]);
return 0;
}
arr is an array. Each element stores the address of an int.
arr[0]isint **arr[0]is the value stored at that address
Step by Step Execution
Consider this example:
#include <stdio.h>
int main(void) {
int numbers[4] = { 5, 10, 15, 20 };
int (*p)[4] = &numbers;
printf("%d\n", (*p)[2]);
return 0;
}
Step-by-step
1. Declare an array
int numbers[4] = { 5, 10, 15, 20 };
numbers is an array of 4 integers.
2. Declare a pointer to the whole array
int (*p)[4] = &numbers;
Read it from p:
*means pointer
Real World Use Cases
Where array-of-pointers is used
List of strings
char *names[3] = { "Alice", "Bob", "Carol" };
Each element points to the first character of a string.
Sparse or flexible row storage
You can store pointers to separately allocated rows in a table-like structure.
int *rows[10];
Each row can point to a different memory block.
Lookup tables
An array of pointers is useful when each entry refers to another object or buffer.
Where pointer-to-array is used
Passing fixed-size arrays to functions
void print_row(int (*row)[8]);
This says the function expects a pointer to an array of 8 integers.
Working with multidimensional arrays
int matrix[5][8];
int (*row)[8] = matrix;
Real Codebase Usage
In real codebases, developers use these forms to make intent explicit.
Common patterns
1. Function parameters for fixed-width rows
void process_rows(size_t count, int (*rows)[8]) {
for (size_t i = 0; i < count; i++) {
printf("%d\n", rows[i][0]);
}
}
This is common with matrices, image data, and protocol packets.
2. Arrays of pointers for dynamic collections
char *errors[5];
Useful when each element may point to a different string or object.
3. Validation and guard clauses
void print_first(int (*arr)[8]) {
if (arr == NULL) {
return;
}
printf("%d\n", (*arr)[0]);
}
Pointer checks are common before dereferencing.
4. APIs that distinguish contiguous memory from indirect storage
Common Mistakes
1. Assuming arrays and pointers are always the same
They are related, but not identical types.
Broken thinking:
int *a[8];
int (*b)[8];
b = a; // wrong: incompatible types
Why it fails:
ais an array of pointersbis a pointer to an array of int
2. Ignoring parentheses
int *a[8]; // array of pointers
int (*a)[8]; // pointer to array
A small change in parentheses creates a different type.
3. Dereferencing the wrong thing
Broken example:
int values[3] = {1, 2, 3};
int (*p)[3] = &values;
printf("%d\n", *p[1]);
Why this is wrong:
Comparisons
| Declaration | Meaning | Typical use |
|---|---|---|
int *a[8] | array of 8 pointers to int | list of addresses, strings, rows |
int (*a)[8] | pointer to array of 8 int | fixed-size arrays, matrix rows |
int a[8] | array of 8 int | direct storage of integers |
int *a | pointer to int | points to one int or first element |
array of pointers vs pointer to array
Cheat Sheet
Quick reading rule
Start at the variable name:
- Look right first
- Then look left
- Parentheses control grouping
[]and()bind tighter than*
Common patterns
int *a[8]; // array of 8 pointers to int
int (*a)[8]; // pointer to array of 8 int
int (*f)(void); // pointer to function returning int
int *f(void); // function returning pointer to int
Your declarations
int *arr1[8]; // array of 8 pointers to int
int (*arr2)[8]; // pointer to array of 8 int
int *(arr3[8]); // same as int *arr3[8]
Important precedence
[]has high precedence
FAQ
What is the difference between int *a[8] and int (*a)[8] in C?
int *a[8] is an array of 8 pointers to int. int (*a)[8] is a pointer to one array of 8 integers.
Are int *arr1[8] and int *(arr3[8]) the same?
Yes. They mean the same thing: an array of 8 pointers to int.
Why do parentheses matter in C declarations?
Parentheses change grouping. Since [] binds more tightly than *, parentheses can force * to apply first.
How do I read complex C declarations correctly?
Start at the variable name, read to the right when possible, then to the left, and use parentheses to determine grouping.
Is an array the same as a pointer in C?
No. Arrays and pointers are different types. Arrays often decay to pointers in expressions, but they are not identical.
What type is &arr if arr is int arr[8]?
Mini Project
Description
Build a small C program that demonstrates the difference between an array of pointers and a pointer to an array. This helps you see that similar-looking declarations can represent very different memory structures and access patterns.
Goal
Create and run a program that prints values using both int *arr[3] and int (*ptr)[3], and observe how access syntax differs.
Requirements
- Declare an array of 3 integers and a pointer to that array.
- Declare three separate integers and an array of 3 pointers to them.
- Print all values from both structures.
- Use the correct syntax for each case:
(*ptr)[i]and*arr[i].
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 printf Format Specifier for bool: How to Print Boolean Values
Learn how to print bool values in C with printf, why no %b/%B specifier exists, and the common patterns to print true/false or 0/1.