Массив указателей, указывающих на 2-мерные массивы - PullRequest
0 голосов
/ 06 марта 2020

Я хочу создать массив указателей, каждый из которых указывает на двумерный массив с плавающей точкой. 2D-массивы определяются следующим образом:

float a[][2] = {{1,0.5},{2,0.5},{3,0.5},{4,0.5}};
float b[][2] = {{1,1},{5,1},{4,0.5},{3,0.5},{2,0.5},{8,1}};
float c[][2] = {{1,0.333},{1,0.333},{1,0.334}};

Каждый из них имеет разное количество строк, но всегда 2 столбца. У меня также есть функция, куда я отправляю один из этих массивов в качестве аргумента, и мне нужно использовать в них некоторые значения. Допустим, это что-то вроде этого (есть другие вещи, связанные с другими значениями, которые мне нужно использовать, но это не слишком относится к вопросу)

void take_values(float arr[][2]){
  printf("%f ", arr[0][0]);
  printf("%f ", arr[0][1]);
}

В main () я использовал функцию в каждом из массивов, подобных этому

take_values(a);
take_values(b);
take_values(c);

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

  1. Как определить массив указателей для каждого из 2D-массивов ?
  2. Как я могу отправить 2D-массивы в качестве аргументов в функции take_values, используя этот массив указателей?
  3. Как получить доступ к указанным c значениям массивов внутри take_values функция? / Нужно ли там использовать указатели или просто оставить их такими, какие они есть сейчас?

Ответы [ 2 ]

2 голосов
/ 07 марта 2020
float (*ptrs[])[2] = {a, b, c};

, который читается как

        ptrs           -- ptrs
        ptrs[]         -- is an array of unknown size
      (*ptrs[])        -- of pointers
      (*ptrs[])[2]     -- to 2-element arrays
float (*ptrs[])[2]     -- of float

, и мы инициализируем его указателями на a, b и c.

Ваше определение функции будет выглядеть так:

void take_values( float (**ptrs)[2] )
{
  ...
}

int main( void )
{
  float (*ptrs[])[2] = {a, b, c};
  ...
  take_values( ptrs );
}

Вы будете индексировать в каждом массиве как

ptrs[i][j][k] 

в main и take_values.

Как мы туда доберемся:

Каждое из выражений a, b и c будет "распадаться" до введите float (*)[2] 1 , поэтому указатель на каждый массив может быть объявлен как

float (*pt1)[2] = a;
float (*pt2)[2] = b;
...

et c. Мы просто объявляем массив указателей для хранения всех трех.

Вы будете индексировать в каждом массиве как

ptrs[i][j][k]

Помните, что a[i] определяется как *(a + i), поэтому

*a == *(a + 0) == a[0]

Это означает, что

(*ptrs[i])[k] == (*(ptrs[i] + 0))[k] == (ptrs[i][0])[k] == ptrs[i][0][k]

Таким образом,

(*(ptrs[i] + j))[k] == (ptrs[i][j])[k] == ptrs[i][j][k]

В main, поскольку ptrs является массивом T, где T это "массив указателей на 2-элементные массивы float", когда вы передаете его функции, он "затухает", чтобы набрать "указатель на T", или "указатель на указатель на 2-элементный массив из float ".

В take_values вы имеете дело с указателем на указатель, поэтому

(**ptrs)[i] == (*(*ptrs + 0))[i] == (*ptrs[0])[i] == (*(ptrs[0] + 0))[i] == (ptrs[0][0])[i]

Обратите внимание, что вам нужен способ указать, насколько большой массив из указателей есть, и сколько строк содержит каждый из массивов.


За исключением случаев, когда он является операндом операторов sizeof или унарных & или является строковым литералом, используемым для инициализации массива символов в объявлении выражение типа "массив N-элементов из T" будет преобразовано ("распад") в выражение типа "указатель на T" и значение выражения будет адрес первого элемента массива.
1 голос
/ 07 марта 2020

Вы могли бы сделать что-то вроде этого:

float a[][2] = {{1,0.5},{2,0.5},{3,0.5},{4,0.5}};
float b[][2] = {{1,1},{5,1},{4,0.5},{3,0.5},{2,0.5},{8,1}};
float c[][2] = {{1,0.333},{1,0.333},{1,0.334}};

float (*arr[])[][2] = {a, b, c};

for (int i = 0; i < sizeof(arr) / sizeof(void *); i++) {
    take_values(arr[i]);
}

Но, конечно, теперь вам придется изменить определение arr, чтобы включить любые дополнительные 2D-массивы, которые у вас есть (но вам придется это сделать независимо от этого.)

Так, например, если вы добавили другой 2D-массив с именем d, вам придется изменить определение:

float (*arr[])[][2] = {a, b, c};

на следующее:

float (*arr[])[][2] = {a, b, c, d};

ПРИМЕЧАНИЕ: будьте осторожны с этим:

i < sizeof(arr) / sizeof(void *);

Если вы когда-нибудь передадите массив двухмерных массивов, он затухнет до указателя, и это выиграет не работает.

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