Разница ч / б, выделяющая память для 2D-массива за один раз или строка за строкой
Как это повлияет на доступ к массиву или на выделение памяти для этих двух случаев:
1.
int **arr;
arr = malloc( sizeof(int) * row * column );
2.
int **arr;
arr = malloc( sizeof(*arr) * row);
for(i=0; i<row; i++)
arr[i] = malloc( sizeof( **arr) * column));
1 ответ
Во-первых, "влияние" заключается в том, что ваш первый метод не работает. Это не будет работать через
int **
указатель.Чтобы выделить двумерный массив в одном кадре, как вы пытаетесь сделать это в своем первом методе, вам фактически нужно выделить одномерный массив достаточного размера.
int *arr = malloc( row * column * sizeof *arr ); // Note: `int *`, not `int **`
и выполнить доступ путем ручного пересчета индекса, например, вместо того, чтобы делать
arr[i][j]
ты должен сделатьarr[i * column + j]
,Попытка сохранить выделенный указатель в
int **arr
а затем получить доступ к вашему массиву какarr[i][j]
просто приведет к сбоям.Во-вторых, ваш второй метод в порядке. Просто во втором методе вам не требуется выделять память второго уровня несколькими независимыми
malloc
звонки. Вы можете выделить всю память второго уровня за один снимокint **arr = malloc( row * sizeof *arr ); int *arr_data = malloc( row * column * sizeof *arr_data );
а затем просто распределить эту предварительно выделенную память второго уровня между строками
for (i = 0; i < row; i++) arr[i] = arr_data + i * column;
(Конечно, вы можете распределять строки независимо, если хотите. Это также сработает. Причина, по которой я хотел выделить их за один раз, состоит в том, чтобы лучше проиллюстрировать сходство между первым и вторым подходом, как прокомментировано ниже.)
Теперь, взглянув на эти два метода, вы можете легко увидеть, что оба они по сути делают одно и то же. Единственное отличие состоит в том, что в первом методе вы находите начало строки на лету, вычисляя arr + i * column
каждый раз (обратите внимание, что arr[i * column + j]
эквивалентно (arr + i * column)[j]
). Во втором методе вы заранее рассчитываете все начала строки, используя тот же arr_data + i * column
и сохраните их для дальнейшего использования в отдельном массиве "индекс строки" arr
,
Таким образом, это в основном сводится к компромиссу между использованием памяти (первый метод требует меньше памяти) и скоростью (второй метод потенциально, но не обязательно, быстрее). В то же время второй метод поддерживает "естественный" синтаксис для доступа к 2D массивам - arr[i][j]
в то время как в первом методе вы должны использовать более сложный синтаксис 1D доступа с пересчетом индекса.