Подтвердить что ты не робот

Карта памяти для 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 выхода одинаковы?

4b9b3361

Ответ 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];

поэтому я думаю, что мой ограниченный отзыв точным.:) надеюсь, что это поможет!