Как создать массив указателей в C?
Чтобы создать массив указателей в C, у вас есть одна опция, которую вы объявляете:
type *array[CONST]; /* create CONST number of pointers to type */
С C99 + вы можете создать массив переменной длины (VLA) указателей, например,
type *array[var]; /* create var number of pointers to type */
Стандарт определяет оба в C11 Standard -6.7.6.2 Объявление массивов и обсуждение подписки в C11 Standard - 6.5.2.1 Подписка на массив .
Краткий пример использования массива указателей, присвоения указателя каждой строке в2D-массив на массив указателей на int
, например,
#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');
}
}
Пример использования / Вывод
$ ./bin/array_ptr2int_vla
0 1 2
3 4 5
6 7 8
9 10 11
12 13 14
Другим фундаментальным для C является указатель на указатель , но это не «массив», хотя обычно он называется «динамическим массивом» и может быть выделен и проиндексирован для имитации массива.Различие между «массивом» и набором указателей заключается в том, что в массиве все значения гарантированно являются последовательными в памяти - такой гарантии нет с набором указателей и мест памяти, на которые они ссылаются.
Так что же int **arr[CONST]
объявляет?
В своем вопросе вы ставите объявление int** arr[5] = {0xbfjeabfbfe,0x...};
, так что же это объявляет?Вы заявляете Пять из чего-то, но что?Вы объявляете пять указатель на указатель на int .Вы можете сделать это?Конечно.
Итак, что вы делаете с указатель на указатель на что-то ?Указатель на poitner формирует основу динамически распределенной и перераспределенной коллекции типов.Их обычно называют «динамически распределенными массивами», но это несколько неверно, потому что нет никакой гарантии, что все значения будут последовательными в памяти.Вы объявите определенное количество указателей на каждый int**
в массиве.Вам не нужно выделять равное количество указателей.
( примечание: нет никакой гарантии, что память, на которую указывают указатели, будет даже последовательной, хотя сами указатели будут - убедитесь, что вы понимаете это различие и что такое "Массив "гарантирует, а что нет указателей)
int** arr[5]
объявляет пять int**
.Затем вы можете назначить любой адрес, который вам нравится, каждому из пяти указателей, при условии, что тип int**
.Например, вы будете назначать указателям что-то похожее на:
arr[i] = calloc (ROW, sizeof *arr[i]); /* allocates ROW number of pointers */
Тогда вы можете свободно выделять любое число int
и назначать этот адрес каждому указателю, например,
arr[i][j] = calloc (COL, sizeof *arr[i][j]); /* allocates COL ints */
Затем вы можете циклически перебирать целые числа, присваивая значения:
arr[i][j][k] = v++;
Краткий пример, использующий ваше распределение типов int** arr[5]
, может быть похож на:
#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;
}
Вы выделили дляиз пяти смоделированных двумерных массивов, присваивающих каждому массиву указатель int **arr[5]
, получится:
Пример использования / Вывод
$ ./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
Надеемся, что это имеетпомог с различием между массивом указателей и массивом указателей на указатель и показал, как объявлять и использовать каждый из них.Если у вас есть какие-либо дополнительные вопросы, не стесняйтесь спрашивать.