Здесь создается технически не двумерный массив, а массив указателей, каждый из которых будет содержать начальный адрес массива. Затем его можно проиндексировать, как если бы это был «настоящий» 2D-массив.
Эта строка создает массив из 5 указателей на int
:
matrix = malloc(5 * sizeof(int*));
Следующая строка создает один массив 20 int
:
*matrix = malloc(20 * sizeof(int));
Это, однако, не является полным с точки зрения двумерного массива, потому что была выделена только одна строка. Вам нужно перебрать все элементы, на которые указывает matrix
, чтобы создать каждую строку:
int **matrix, i;
matrix = malloc(5 * sizeof(int*));
for (i=0; i<5; i++) {
matrix[i] = malloc(20 * sizeof(int));
}
Когда вы закончите использовать этот динамический 2D массив, вам нужно будет освободить память в обратном порядке:
for (i=0; i<5; i++) {
free(matrix[i]);
}
free(matrix);
Это несколько отличается от реального 2D-массива. Во-первых, в истинном двумерном массиве все элементы непрерывны в памяти, тогда как в этом случае массив указателей и каждый массив строк не совпадают.
Другое отличие состоит в том, что при передаче в функцию вы не можете передать ее так же, как при передаче реального 2D-массива.
Для простого одномерного массива, выделенного во время компиляции или динамически:
int a1[5];
int *a2 = malloc(5 * sizeof(int));
И то, и другое может быть передано такой функции:
void f(int *a);
Но в случае двумерного массива:
int a[5][20];
Это должно быть передано функции, подобной этой:
void f(int a[5][20]);
или эквивалентно:
void f(int (*a)[20]);
Принимая во внимание, что динамический 2D-массив должен быть передан функции, подобной этой:
void f(int **a);