Historically, pointers became the foundation of memory work in the C language and provided a flexible mechanism for efficient access to array elements and dynamic structures. However, the syntax and semantics of pointers to arrays and arrays of pointers often cause confusion.
Problem: Beginners often confuse pointer to array and array of pointers, leading to improper memory usage, parameter passing errors, and difficult-to-construct syntax errors.
Solution:
Example declaration and usage:
// Pointer to an array of 10 int: int (*p)[10]; int arr[10]; p = &arr; // Array of 10 pointers to int int *ap[10]; for (int i = 0; i < 10; ++i) { ap[i] = &arr[i]; } // How to get an element using a pointer to an array: (*p)[2] = 5; // the third element of arr // How to get a value using an array of pointers: *ap[2] = 8; // the third element of arr via ap
Key features:
**Are int p[10] and int (p)[10] the same?
No. int *p[10] is an array of 10 pointers to int. int (*p)[10] is a pointer to an array of 10 int. A lot of confusion arises without the parentheses!
Code example:
int arr[10]; int *p[10]; // array of pointers int (*q)[10] = &arr; // pointer to an array
*Can a regular pointer to int be freely assigned to a variable of type int (p)[10]?
No. A regular int * points to a single element, while int (*p)[10] points to an array of 10 integers; the types are incompatible without explicit casting.
How to properly pass a two-dimensional array to a function?
You need to explicitly specify the size of the second dimension:
void foo(int a[][4], int n); // array of n rows with 4 elements
or use a pointer to an array:
void bar(int (*a)[4], int n);
An engineer declares a variable as int *p[10], tries to assign it &arr, where arr is int arr[10] and accesses it as an array, resulting in a compilation error or invalid behavior.
Pros:
Cons:
A developer carefully uses parentheses: int (*p)[10], clearly understands the difference, correctly passes arrays to functions, uses typedef for easier declarations.
Pros:
Cons: