В чем разница между указателями на 2d-массив и * arr []? - PullRequest
2 голосов
/ 17 апреля 2019

Я пытаюсь понять, в чем разница между таким массивом:

int arr[2][2] = {{0, 1}, {2, 3}};
int* pArr = (int*)arr;
for(int i = 0; i < 4; i++)
{
    printf("%d ", pArr[i]);
}

и этим:

int* foo[2] = {arr1, arr2}; // Let's say the length of arr1 is 3 and arr2 is 1
int* pFoo = (int*)foo;
for(int i = 0; i < 4; i++)
{
    printf("%d ", pFoo[i]);
}

Они выглядят примерно так же, новыходной совершенно другой.Я получаю странные результаты, если я делаю то, что я привел здесь в качестве примера, чем это дает мне большие целые числа, но если я добавляю больше массивов и элементов, это дает мне и меньшие целые числа.пример вывода: Вывод

* в исходящем изображении: верхние целые числа - это первый двумерный массив, а нижние целые числа - второй указатель массива.

Может кто-нибудь объяснитьпожалуйста, почему это происходит?

Ответы [ 2 ]

2 голосов
/ 17 апреля 2019

Многомерный массив - это отдельный блок памяти. Массив указателей на данные, которые не обязательно являются смежными (один блок).

Последний полезен для управления разреженными массивами или в тех случаях, когда каждый указатель на подмассив не обязательно имеет одинаковый размер.

1 голос
/ 17 апреля 2019

Может кто-нибудь объяснить мне, пожалуйста, почему это происходит?

С ...

int* foo[2] = {arr1, arr2}; // Let's say the length of arr1 is 3 and arr2 is 1

... foo объявляется как массив, элементы которого имеют тип int *. Вы не представляете определения arr1 и arr2, но допустим, что они являются массивами int - тогда в выражениях инициализатора они «распадаются» на указатели на свои первые элементы, которые имеют правильный тип для элементов foo, так что все в порядке.

Но указатели не целые числа. Вы объявляете pFoo как int *, но инициализируете его int ** , преобразованным в int *:

int* pFoo = (int*)foo;

Преобразование типа указателя ничего не делает с данными, на которые он (фактически) указывает, и поскольку pFoo в конечном итоге указывает на данные, которые на самом деле не int s, доступ к этим данным через pFoo приводит к неопределенному поведению .

Возможно, вы искали это:

int **pFoo2 = foo;  // note: no cast needed

Теперь тип pFoo2, int **, совпадает с типом, к которому foo естественным образом распадается, и вы можете правильно получить доступ к элементам:

printf("%d", pFoo2[0][0]);

Обратите внимание, что вы по-прежнему обращаетесь к arr1 и arr2 через pFoo2, косвенно. Вы все равно должны уважать их длину, даже если эти длины не совпадают друг с другом и не очевидны для типа pFoo2 или foo.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...