Предположим, что у меня есть двумерный массив grid
, объявленный как double grid[5][5]
. Я понимаю, что справедливы следующие утверждения:
- когда объявляется
grid
, смежный блок памяти выделяется для 5 * 5 удвоений, не более того, - когда к элементу массива обращается обозначение
grid[i][j]
, этот фрагмент кода фактически интерпретируется как*(grid+(i*5+j))
.
С другой стороны, я знаю, что я также могу сохранить ту же матрицу, что и массив указателей, написав что-то вроде:
double ** grid;
grid = (double**)malloc(sizeof(double*)*5);
for (i=0; i<5; i++)
grid[i] = (double*)malloc(sizeof(double)*5);
и у меня есть код, который делает это. Проблема в том, что он затем переходит к элементам grid
, как и раньше, с двойной надписью. Разве этот случай отличается? В этом случае grid[i][j]
преобразуется в *(*(grid+i)+j)
, т.е. В двойное разделение? Это единственный способ увидеть, как это происходит правильно.
(Этот вопрос, вероятно, связан с моим (отсутствием) понимания взаимосвязи между типами указателей и массивов в C...)
EDIT:
Хорошо, посмотрим, получилось ли это прямо:
-
grid[i][j]
всегда преобразуется в*(*(grid+i)+j)
; - это выражение действительно вычисляется по-разному в двух случаях, поскольку, как утверждает Джим в своем ответе, арифметика указателя учитывает размер указанного типа; тем не менее, правильный элемент извлекается в обоих случаях;
- тогда и только тогда, когда "сетка" является двумерным массивом, это выражение дополнительно оптимизировано до
*( (double*)grid + (i*5+j) )
, что возможно, потому что компилятор знает, что любойgrid[i]
фактически является массивом, начинающимся с местоположенияgrid+i*5
.
Но это оставляет мне неизбежный вывод: для 2D-массива, если я устанавливаю i=j=0
, то у меня есть это **grid == *((double*)grid)
. Правильно ли это?