2d массив путаницы - PullRequest
       1

2d массив путаницы

0 голосов
/ 04 сентября 2010

Почему к памяти двумерного массива обращаются два параметра, а не только один (игнорируя указатели). Почему диаграмма памяти представлена ​​в виде строк и столбцов, а не прямой (горизонтальной)?он сказал, что 2d массив является массивом массивов, но я не понимаю этого.

Ответы [ 4 ]

7 голосов
/ 04 сентября 2010

Речь идет об удобстве. Конечно, память на самом деле все последовательная, но иногда хочется иметь доступ к вещам с двумя индексами (например, реализуя матрицы).

Рассмотрим массив 3х3. Удобно думать о памяти так:

----------------------------
| [0][0] | [0][1] | [0][2] |
|--------------------------|
| [1][0] | [1][1] | [1][2] |
|--------------------------|
| [2][0] | [2][1] | [2][2] |
----------------------------

Но в памяти это, конечно, действительно выглядит так:

----------------------------------------------------------------------------------
| [0][0] | [0][1] | [0][2] | [1][0] | [1][1] | [1][2] | [2][0] | [2][1] | [2][2] |
----------------------------------------------------------------------------------

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

Эта картинка также должна помочь вам понять, почему ее можно считать массивом массивов. Вот слегка измененная картинка для акцента:

|||--------------------------|||--------------------------|||--------------------------|||
||| [0][0] | [0][1] | [0][2] ||| [1][0] | [1][1] | [1][2] ||| [2][0] | [2][1] | [2][2] |||
|||--------------------------|||--------------------------|||--------------------------|||

Как видите, там действительно три одномерных массива. Итак, когда вы пишете array[1], вы ссылаетесь на второй одномерный компонент полного двумерного массива, то есть на вторую группу из трех в памяти. При добавлении второго индекса, array[1][2] берет третий элемент этого одномерного массива, приводя вас к нужному элементу двумерного массива.

1 голос
/ 04 сентября 2010

Это та же самая причина, по которой вы не пишете двумерную матрицу как последовательность целых чисел в своей математической тетради.Это просто означает, что они представляют две разные особенности.Например, пиксели на экране могут быть представлены в виде одного массива, используя A[i] { i => 0 to N^2 }, но когда кто-то запрашивает у вас 4-й пиксель в 10-й строке, вы не хотите выполнять умножение самостоятельно каждый раз, верно?Вместо этого вы просто возвращаете A[10][4].

1 голос
/ 04 сентября 2010

все дело в различиях между:

 1  2  3  4  5  6  7  8  9  
[A][A][A][A][A][X][A][A][A]

и

      1  2  3  4  5  6  7  8 
  1  [A][A][A][A][A][A][A][A]
  2  [A][A][A][A][A][A][A][A]
  3  [A][A][A][A][A][A][A][A]
  4  [A][A][A][A][X][A][A][A]
  5  [A][A][A][A][A][A][A][A]
  6  [A][A][A][A][A][A][A][A]

найти Х в приведенных выше данных:

в первом, чтобы получить доступ к адресу, вам нужен ОДИН индекс (6 - это местоположение X)

, но во втором у вас есть ДВА индекса для определения адреса (4: 5 - это местоположение X).

Вы можете рассматривать вторую таблицу как массив первого массива.

Обратите внимание, что распределение памяти для этих массивов отличается от того, что вы видите в моем примере. Мой образец просто для лучшего понимания

0 голосов
/ 04 сентября 2010

Ответы выше в порядке. Но они рассказывают только половину истории. Теперь я расскажу вам другую половину, где вы должны и должны иметь две переменные для индексации в двумерном массиве. Это когда вы объявляете двумерный массив в куче, а не в стеке. Распространенный вопрос интервью на C: «Как вы будете динамически создавать двумерный массив?».

Фрагмент кода выглядит следующим образом: -

int **p = (int **)malloc(n * sizeof(int*));</p> <p>for(int i =0;i < n;i++){</p> <p>p[i] = (int *)malloc(n * sizeof(int));</p> <p>}

В этом случае, если вы хотите перейти к элементу второго столбца третьей строки, вы не можете сделать как int elem = p[2*n + 1]. Простая причина в том, что типы не совпадают, p [2 * n + 1] имеет тип int *. Чтобы получить нужный элемент, вы должны сделать p [2] [1].

А также, пожалуйста, не игнорируйте комментарии к вопросу. Естественное понятие двумерного массива состоит в том, что любые элементы внутри будут нуждаться в двух перенаправлениях, чтобы достичь его. Доступ к нему за один шаг не имеет никакого значения. Это может даже не закрепить вещи.

Чтобы понять, о чем я говорю, рассмотрим массив, объявленный как int p[20][20]; Теперь, если вы думаете, что доступ к p [2] [1] медленнее, чем доступ к p [2 * 20 +1], вы снова ошибаетесь. Зачем? Потому что внутренне компилятор делает то же самое. Максимальное количество микросекунд времени компиляции будет сохранено. И знаете ли вы, кому нужно экономить несколько микросекунд во время компиляции?

Nobody.

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