Из Output 1/2 видно, что одномерный (вектор) и многомерный массивы хранятся в памяти одинаково - в виде вектора [x1, x2, x3, x4] (запись идет по-строкам). При этом a и b - указатели на векторы, т. е. хранят адреса, по которым размещены векторы.
Вопрос вызывает Output 3. Если разобрать выражение *((*(a+i))+j)), получится:
1. К адресу первого элемента прибавляем число равное произведению индекса i и размера элемента.
2. Полученное в п1 значение трактуется как адрес переменной (указатель). Из этого адреса извлекается значение (происходит разыменование указателя) и складывается со вторым индексом j умноженным на размер элемента.
3. Полученное в п2 значение трактуется как адрес переменной (указатель). Из этого адреса извлекается значение (выполняется второе разыменование указателя) которое и является результатом выражения.
Как, при всем этом, Output 3 может работать правильно? Ведь у нас переменная "a" указатель на «одномерный» массив, а не указатель на массив указателей. Откуда _два_ разыменования?
указатель на одномерный массив
&---& &-------------------&
| a |------>| x1 | x2 | x3 | x4 |
&---& &-------------------&
указатель на массив указателей
&---& &---------&
| a |------>| x1 | x2 |
&---& &---------&
| |
| |
V V
&--& &--&
|y1| |y1|
|y2| |y2|
&--& &--&
#include <stdio.h>
int main() {
int i, j;
int a[2][2]={{1, 2},
{3, 4}};
int b[4]={1, 2, 3, 4};
printf("Output 1: ");
for (i=0; i < 2; i++)
for (j=0; j < 2; j++)
printf("%d ",((int*)a)[i*2+j]);
printf("\nOutput 2: ");
for (i=0; i < 2; i++)
for (j=0; j < 2; j++)
printf("%d ",b[i*2+j]);
printf("\nOutput 3: ");
for (i=0; i < 2; i++)
for (j=0; j < 2; j++)
printf("%d ",*((*(a+i))+j));
printf("\n");
return 0;
}
$ ./test
Output 1: 1 2 3 4
Output 2: 1 2 3 4
Output 3: 1 2 3 4