Разница ч / б, выделяющая память для 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 доступа с пересчетом индекса.

Другие вопросы по тегам