Can we create an array of pointers in C?
What is the advantage of using an array of pointers in C?
What is a pointer of pointer in C?
How do you create an array of pointers in C?
To create an array of pointers in C, you have one option, you declare:
type *array[CONST]; /* create CONST number of pointers to type */
With C99+ you can create a Variable Length Array (VLA) of pointers, e.g.
type *array[var]; /* create var number of pointers to type */
The standard defines both in C11 Standard - 6.7.6.2 Array declarators and discusses subscripting in C11 Standard - 6.5.2.1 Array subscripting.
A short example using an array of pointers, assigning a pointer to each row in a 2D array to an array of pointers to int, e.g.
#include <stdio.h>
#include <stdlib.h>
#define COL 3
#define MAX 5
int main (void) {
int arr2d[MAX][COL] = {{ 0 }}, /* simple 2D array */
*arr[MAX] = { NULL }, /* 5 pointers to int */
i, j, v = 0;
for (i = 0; i < MAX; i++) { /* fill 2D array */
for (j = 0; j < COL; j++)
arr2d[i][j] = v++;
arr[i] = arr2d[i]; /* assing row-pointer to arr */
}
for (i = 0; i < MAX; i++) { /* for each pointer */
for (j = 0; j < COL; j++) /* output COL ints */
printf (" %4d", arr[i][j]);
putchar ('\n');
}
}
Example Use/Output
$ ./bin/array_ptr2int_vla
0 1 2
3 4 5
6 7 8
9 10 11
12 13 14
Another fundamental of C is the pointer-to-pointer, but it is not an "Array", though it is routinely called a "dynamic array" and can be allocated and indexed simulating an array. The distinction between an "Array" and a collection of pointers is that with an Array, all values are guaranteed to be sequential in memory -- there is no such guarantee with a collection of pointers and the memory locations they reference.
So What Does int **arr[CONST] Declare?
In your question you posit a declaration of int** arr[5] = {0xbfjeabfbfe,0x...};, so what does that declare? You are declaring Five of something, but what? You are declaring five pointer-to-pointer-to-int. Can you do that? Sure.
So what do you do with a pointer-to-pointer-to-something? The pointer-to-poitner forms the backbone of dynamically allocated and reallocated collection of types. They are commonly termed "dynamically allocated arrays", but that is somewhat a misnomer, because there is no guarantee that all values will be sequential in memory. You will declare a given number of pointers to each int** in the array. You do not have to allocate an equal number of pointers.
(note: there is no guarantee that the memory pointed to by the pointers will even be sequential, though the pointers themselves will be -- make sure you understand this distinction and what an "Array" guarantees and what pointers don't)
int** arr[5] declares five int**. You are then free to assign any address to you like to each of the five pointers, as long as the type is int**. For example, you will allocate for your pointers with something similar to:
arr[i] = calloc (ROW, sizeof *arr[i]); /* allocates ROW number of pointers */
Then you are free to allocate any number of int and assign that address to each pointer, e.g.
arr[i][j] = calloc (COL, sizeof *arr[i][j]); /* allocates COL ints */
You can then loop over the integers assigning values:
arr[i][j][k] = v++;
A short example using your int** arr[5] type allocation could be similar to:
#include <stdio.h>
#include <stdlib.h>
#define ROW 3
#define COL ROW
#define MAX 5
int main (void) {
int **arr[MAX] = { NULL }, /* 5 pointer-to-pointer-to-int */
i, j, k, v = 0;
for (i = 0; i < MAX; i++) { /* allocate ROW pointers to each */
if ((arr[i] = calloc (ROW, sizeof *arr[i])) == NULL) {
perror ("calloc - pointers");
return 1;
}
for (j = 0; j < ROW; j++) { /* allocate COL ints each pointer */
if ((arr[i][j] = calloc (COL, sizeof *arr[i][j])) == NULL) {
perror ("calloc - integers");
return 1;
}
for (k = 0; k < COL; k++) /* assign values to ints */
arr[i][j][k] = v++;
}
}
for (i = 0; i < MAX; i++) { /* output each pointer-to-pointer to int */
printf ("pointer-to-pointer-to-int: %d\n\n", i);
for (j = 0; j < ROW; j++) { /* for each allocated pointer */
for (k = 0; k < COL; k++) /* output COL ints */
printf (" %4d", arr[i][j][k]);
free (arr[i][j]); /* free the ints */
putchar ('\n');
}
free (arr[i]); /* free the pointer */
putchar ('\n');
}
return 0;
}
You have allocated for five simulated 2D arrays assigning the pointer to each to your array of int **arr[5], the output would be:
Example Use/Output
$ ./bin/array_ptr2ptr2int
pointer-to-pointer-to-int: 0
0 1 2
3 4 5
6 7 8
pointer-to-pointer-to-int: 1
9 10 11
12 13 14
15 16 17
pointer-to-pointer-to-int: 2
18 19 20
21 22 23
24 25 26
pointer-to-pointer-to-int: 3
27 28 29
30 31 32
33 34 35
pointer-to-pointer-to-int: 4
36 37 38
39 40 41
42 43 44
Hopefully this has helped with the distinction between an array of pointers, and an array of pointers-to-pointer and shown how to declare and use each. If you have any further questions, don't hesitate to ask.
An array of pointers to ints;
int x = 1;
int y = 42;
int z = 12;
int * array[3];
array[0] = &x;
array[1] = &y;
array[2] = &z;
alternate syntax
int * array[] = {&x,&y,&z};
keeping it simple. Work upwards from there