Я попытаюсь нарисовать, как
int array[10][6];
и
int **array2 = malloc(10 * sizeof *array2);
for (int i = 0; i < 10; ++i)
array2[i] = malloc(6 * sizeof **array2);
выглядят в памяти и как они различаются (и что их нельзя разыграть
array
выглядит так:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
| | | | | | | | | | | | | ..............| | | (10*6 elements of type int)
- - - - - - - - - - - - - - - - - - - - - -
< first row >< second row> ...
array2
выглядит так:
_ _ _ _ _ _ _ _ _ _
| | | | | | | | | | | (10 elements of type int *)
- - - - - - - - - -
| | .... | _ _ _ _ _ _
| | \-->| | | | | | | (6 elements of type int)
| | - - - - - -
| |
| | _ _ _ _ _ _
| \ -->| | | | | | | (6 elements of type int)
| - - - - - -
|
|
| _ _ _ _ _ _
\ -->| | | | | | | (6 elements of type int)
- - - - - -
Когда вы говорите array[x][y]
, это переводится в*((int *)array+x*6+y)
Хотя, когда вы говорите array2[x][y]
, это переводится в *(*(array2+x)+y)
(Обратите внимание, что для array
эта формула также работает (прочитайте в конце поста, а затем комментарии)).
То есть статический 2d-массив на самом деле представляет собой 1d-массив со строками, помещенными в одну строку.Индекс рассчитывается по формуле row * number_of_columns_in_one_row + column
.
Динамический двумерный массив, однако это всего лишь одномерный массив указателей.Каждый указатель затем динамически распределяется, чтобы указывать на другой 1d массив.По правде говоря, этот указатель может быть чем угодно.Может быть NULL
, либо указывать на одну переменную, либо указывать на другой массив.И каждый из этих указателей устанавливается индивидуально, поэтому они могут иметь различную природу.
Если вам нужно куда-то передать указатель array
, вы не можете привести его к int **
(представьте, что произойдет. int
значения ячеек array
интерпретируются как указатели и разыменовываются -> Bam! Ошибка сегментации!).Однако вы можете думать о array
как о 1d массиве int [6]
s;это массив элементов 1d типа int [6]
.Чтобы записать это, вы говорите
int (*p)[6] = array;