Рубрики

Многомерная арифметика с указателями в C / C ++

В C / C ++ массивы и указатели имеют сходную семантику, за исключением информации о типе.

В качестве примера приведен трехмерный массив

int buffer[5][7][6];

Элемент в местоположении [2] [1] [2] может быть доступен как « buffer [2] [1] [2] » или * (* (* (buffer + 2) + 1) + 2) .

Соблюдайте следующую декларацию

T *p; // p is a pointer to an object of type T

Когда указатель p указывает на объект типа T, выражение * p имеет тип T. Например, буфер имеет тип массива из 5 двумерных массивов. Тип выражения * buffer — «массив массивов (т.е. двумерный массив)».

Основываясь на вышеупомянутой концепции, перевод выражения * (* (* (buffer + 2) + 1) + 2) шаг за шагом делает его более понятным.

  1. буфер — массив из 5 двумерных массивов, то есть его тип — «массив из 5 двумерных массивов».
  2. buffer + 2 — смещение для 3-го элемента в массиве из 5 двумерных массивов.
  3. * (buffer + 2) — разыменование, то есть его тип теперь двумерный массив.
  4. * (буфер + 2) + 1 — смещение для доступа ко 2-му элементу в массиве из 7 одномерных массивов.
  5. * (* (buffer + 2) + 1) — разыменование (доступ), теперь тип выражения « * (* (buffer + 2) + 1) » представляет собой массив целых чисел.
  6. * (* (buffer + 2) + 1) + 2 — смещение для получения элемента на 3-й позиции в одномерном массиве целых чисел.
  7. * (* (* (buffer + 2) + 1) + 2) — доступ к элементу в 3-й позиции (общий тип выражения теперь int ).

Компилятор вычисляет «смещение» для доступа к элементу массива. «Смещение» рассчитывается на основе размеров массива. В приведенном выше случае смещение = 2 * ( 7 * 6 ) + 1 * ( 6 ) + 2 . Размеры, выделенные синим цветом, являются размерами, обратите внимание, что более высокий размер не используется при расчете смещения . Во время компиляции компилятор знает размеры массива. Используя смещение, мы можем получить доступ к элементу, как показано ниже,

element_data = *( (int *)buffer + offset );

Не всегда возможно объявить размеры массива во время компиляции. Иногда нам нужно интерпретировать буфер как объект многомерного массива. Например, когда мы обрабатываем трехмерное изображение, размеры которого определяются во время выполнения, обычные правила индексации массива не могут быть использованы. Это связано с отсутствием фиксированных размеров во время компиляции. Рассмотрим следующий пример:

int *base;

Где base указывает большой буфер изображения, который представляет трехмерное изображение размера lxbxh, где l, b и h являются переменными. Если мы хотим получить доступ к элементу в местоположении (2, 3, 4), нам нужно рассчитать смещение элемента как

смещение = 2 * (bxh) + 3 * (ч) + 4 и элемент расположен в основании + смещение .

Обобщая далее, учитывая начальный адрес (скажем, базовый ) массива размеров [ lxbxh ], мы можем получить доступ к элементу в произвольном месте ( a, b, c ) следующим образом:

data = * (base + a * ( bxh ) + b * ( h ) + c); // Обратите внимание, что мы не использовали более высокое измерение l .

Та же концепция может быть применена к любому количеству измерений. Нам не нужно более высокое измерение, чтобы вычислить смещение любого элемента в многомерном массиве. Это причина того, что мы пропускаем более высокое измерение, когда мы передаем многомерные массивы функциям . Более высокое измерение требуется только тогда, когда программист перебирает ограниченное количество элементов более высокого измерения.

Загадка AC / C ++, предсказать вывод следующей программы

int main()

{

    char arr[5][7][6];

    char (*p)[5][7][6] = &arr;

  

    / * Подсказка: & arr - имеет тип const указатель на массив

       5 двумерных массивов размером [7] [6] * /

  

    printf("%d\n", (&arr + 1) - &arr);

    printf("%d\n", (char *)(&arr + 1) - (char *)&arr);

    printf("%d\n", (unsigned)(arr + 1) - (unsigned)arr);

    printf("%d\n", (unsigned)(p + 1) - (unsigned)p);

  

    return 0;

}

Выход:

1

210

42

210

Спасибо студенту за указание на ошибку.

Венки . Пожалуйста, пишите комментарии, если вы обнаружите что-то неправильное или вы хотите поделиться дополнительной информацией по обсуждаемой выше теме.

Рекомендуемые посты:

Многомерная арифметика с указателями в C / C ++

0.00 (0%) 0 votes