Разность b/w, выделяющая память для 2D-массива в 1 go или ряд за строкой

что могло бы повлиять на доступ к массиву или распределение памяти для этих двух случаев:

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 **.

    Чтобы выделить 2D-массив одним выстрелом, когда вы пытаетесь сделать это в своем первом методе, вам фактически необходимо выделить 1D-массив достаточного размера

    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.

Таким образом, это в основном сводится к компромиссу между использованием памяти (первый метод требует меньше памяти) и скоростью (второй метод потенциально, но не обязательно, быстрее). В то же время второй метод поддерживает "естественный" синтаксис для доступа к двумерному массиву - arr[i][j], в то время как в первом методе вы должны использовать более сложный синтаксис доступа 1D с пересчетом индекса.