Карта памяти для 2D-массива в C
Считаете ли вы, что эта дискуссия о карте памяти 2D-массива верна? Особенно это фото? Вы можете объяснить теорию?
Предположим, что мы объявляем 2D-массив в C следующим образом:
int arr[3][3]={10, 20, 30, 40, 50, 60, 70, 80, 90};
Теперь, согласно этому обсуждению, память будет располагаться следующим образом:
![enter image description here]()
Теперь для проверки этой теории я написал следующий код:
#include <stdio.h>
main()
{
int arr[3][3]={10, 20, 30, 40, 50, 60, 70, 80, 90};
printf(" arr==%d\n", arr);
printf(" &arr[0]==%d\n", &arr[0]);
printf(" arr[0]==%d\n", arr[0]);
printf("&arr[0][0]=%d\n", &arr[0][0]);
printf(" arr[0][0]=%d\n", arr[0][0]);
}
/*
Output:
========
arr ==1245028
&arr[0] ==1245028
arr[0] ==1245028
&arr[0][0]==1245028
arr[0][0]==10
Press any key to continue...
*/
Почему первые 4 выхода одинаковы?
Ответы
Ответ 1
В вашем коде просто используется простой многомерный массив, но изображение описывает массив указателей, например, тот, который вы обычно делаете, когда делаете malloc-ing.
Многомерный массив - это просто обычный, сплющенный массив (в памяти) с некоторым дополнительным синтаксическим сахаром для доступа. Поэтому, хотя можно получить указатель от arr [i], нет никакой дополнительной "переменной", просто чтобы сохранить это, как это происходит на вашем изображении.
Чтобы исправить изображение, удалите части с помощью arr[0], arr[1]...
и измените значение arr
на 1245039
(то же, что и [amp; arr [0] [0]).
Ответ 2
Посмотрите мой вопрос здесь.
Это не так, как вы получаете доступ к информации о 2-х массивах. Фактически, вы можете просто думать о них как о 1-й, где вы умножаете и добавляете индексы особым образом.
например.
int x[10] = {0,1,2,3,4,5,6,7,8,9};
int y[2][5] = {{0,1,2,3,4},{5,6,7,8,9}};
Они отформатированы точно так же в памяти, и они выглядят так:
|0|1|2|3|4|5|6|7|8|9|
Итак, чтобы получить элемент 8
, вы можете запросить x[8]
или y[1][3]
.
Во втором случае вы можете думать о нем как (1 * 5) + 3
.
Вот почему ваши первые 4 были одинаковыми. У вас есть:
-
arr
: это адрес начала массива
-
arr[0]
: это адрес начала первого вспомогательного массива, который совпадает с началом общего массива
-
&arr[0][0]
: это адрес первого элемента первого вспомогательного массива, а также начало общего массива
-
arr[0][0]
: это значение, хранящееся в первом элементе первого подматрица.
Ответ 3
Первые четыре выхода одинаковы, почему нужно получить адрес первого элемента в массиве, то есть & arr [0] [0]. Последним выходом является его содержимое.
Ответ 4
Хорошо, насколько я помню, в С++ (и я думаю, что C, хотя это не моя сильная сторона), массив 2d, объявленный как Values[][]
, обычно (не знаю, всегда) реализован как массив C- стиль массивов. однако, когда вы объявляете их в стеке (например, локальная переменная), я считаю, что форматирование памяти отличается.
поэтому, когда вы объявляете локальную переменную, все выкладывается так, как если бы это был всего лишь 1-й массив, и вы делаете вещи, которые вы можете наложить на указатель, а затем получить доступ как массив 1D. (!) однако он все равно распознается так же, как обычный 2D-массив в пределах области объявления, и, возможно, если вы перейдете к параметру, который объявлен с помощью обозначения []
.
но если вы выделяете одну из них в кучу (например, глобальную или статическую или через новую), история отличается. теперь память выставляется как фактический массив массивов, и поэтому фактические результаты местоположений памяти, которые вы индексируете, если вы отбрасываете 1D-массив и индекс, теперь будут указателями.
i подтвердил свой отзыв, выполнив следующее: я создал int HeapArray[3][3];
как глобальный и int StackArray[3][3];
как локальный (оба с инициализаторами { { 10, 20, 30 }, {40, 50, 60}, {70, 80, 90 } }
). внутри моей функции я отбросил оба из них на указатель int, int* ptrHeapArray = (int*)HeapArray;
и int* ptrStackArray = (int*)StackArray;
, а затем посмотрел на возвращаемое значение 0-го элемента каждого из них.
[edit: whoops, я их отменил; теперь исправлено]
ptrStackArray[0]
было равно 10
ptrHeapArray[0]
был равен указателю на int [3];
поэтому я думаю, что мой ограниченный отзыв точным.:) надеюсь, что это поможет!