Они не одинаковы.Первая (int a[100][100]
) - это отдельная переменная, которая является составным объектом.Другой (int **p
) - это коллекция массивов, которые вы используете в качестве структуры данных для матриц.
Если вы хотите иметь фактический 2D-массив в динамическом хранилище, вот как вы это делаете:
#include <stdlib.h>
int main()
{
int (*m)[100][100];
m = malloc(sizeof *m);
for (int i = 0; i < 100; i++)
for (int j = 0; j < 100; j++)
(*m)[i][j] = 0;
}
Конечно, синтаксис немного странный, и вы бы предпочли иметь динамическую матрицу с переменным числом столбцов и строк, поэтому вы бы предпочли объявить матрицу, указанную int **p
.
Причина, по которой a
и *a
дают один и тот же вывод, заключается в том, что оба они затухают в указателе на первый элемент a
, который равен a[0][0]
.С другой стороны, p
- это сам указатель, а *p
- это содержимое переменной, на которую указывает p
.Они такие же разные, какими они были бы, если бы вы сделали это:
int d = 0;
int *p = &d;
printf("%p\n", p);
printf("%d\n", *p);
Теперь вернемся к вашему int **p
.
Да, вы можете получить доступ к int a[][100]
и int **p
с двойной индексацией.Однако существует принципиальное различие в способах обработки компилятором a[i][j]
и p[i][j]
.
В a[i][j]
каждый a[i]
представляет собой массив из 100 целочисленных объектов.Таким образом, чтобы получить доступ к i
-ому элементу, а затем к j
-ому элементу, компилятор должен получить доступ к i*100+j
-ому элементу из a[0][0]
.Этот доступ может быть выполнен за один шаг с некоторой индексной арифметикой.
В v[i][j]
каждый v[i]
является указателем, который может указывать на объекты, удаленные друг от друга в памяти.Чтобы получить доступ к элементу v[i][j]
, компилятор должен сначала следовать p
к массиву *p
, а затем найти i
-й элемент в этом массиве, который является указателем на массив p[i]
.И затем с некоторой арифметикой указателя он найдет j
-й элемент этого массива.