Динамический многомерный массив в C - PullRequest
2 голосов
/ 04 января 2012

читая несколько статей о динамическом распределении памяти для многомерных массивов в c, я наткнулся на следующий фрагмент кода: ( ссылка на статью)

#define COLS 5

int (*rptr)[COLS];

    int main(void)
        {
            int nrows = 10;
            int row, col;
            rptr = malloc(nrows * COLS * sizeof(int));
            for (row = 0; row < nrows; row++)
              for (col = 0; col < COLS; col++)
                    rptr[row][col] = 17;
            return 0;
        }

Здесь многомерный массив определяется как int (* rptr) [COLS] и затем динамически связывается с malloc (nrows * COLS * sizeof (int)).

Теперь вопрос в том, как работает наведение, например: если адрес наведения начинается с 100, 101, 102 ... и т. Д.

(если для простоты int требуется 1 байт)

rptr[0] points to ->  100 
rptr[1] points to ->  105 

Компилятор внутренне связывает адрес соответственно на основе размера столбца, как только выполняется malloc (nrows * COLS * sizeof (int))?

Спасибо

1 Ответ

4 голосов
/ 04 января 2012

Рассмотрим это обычное распределение массива:

int* a = malloc(sizeof(int) * 10);

Тип "int *" - это, конечно, указатель на int и sizeof (* a) == sizeof (int). Когда мы делаем [3], это преобразуется в:

*(a + 3)

который (при условии, что sizeof (long) == sizeof (void *)) разыменовывает адрес:

(long)a + 3*sizeof(*a) == (long)a + 3*sizeof(int)

Способ думать о вашем примере кода состоит в том, что тип "int (* rptr) [COLS]" является указателем на (статический, одномерный) массив int размера COLS. Другими словами, sizeof (* rptr) == COLS * sizeof (int). Однако, как и в случае с «int *», мы можем выделить массив этих объектов одномерного массива фиксированного размера. Индексирование "rptr [row]" преобразуется в:

*(rptr + row)

который разыменовывает адрес:

(long)rptr + row*sizeof(*rptr) == (long)rptr + row*COLS*sizeof(int)

Результирующий тип - "int [COLS]", поэтому он может быть снова проиндексирован с помощью "[col]". Вычисление адреса заканчивается тем, что вы хотите:

(long)rptr + row*COLS*sizeof(int) + col*sizeof(int)

Это решение упоминается в http://c -faq.com / aryptr / dynmuldimary.html и работает только в том случае, если число столбцов (или вообще все, кроме первого измерения) фиксировано в время компиляции. Синтаксис становится немного грязным, так как количество измерений увеличивается. Если вам нужно более одного измерения, которое будет определяться динамически во время выполнения, см. Эту страницу для других стратегий.

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