Как правильно записывать многомерные массивы в функции в C++

Как правильно записывать многомерные массивы в функции в C++ ?

#include <iostream>

using namespace std;

void FuncArr(int arr[][], const int row, const int col) { //Неправильная запись
    int arr[][];
}

int main() {
    setlocale(LC_ALL, "ru");
    const int ROW = 5, COL = 3;
    int arr[ROW][COL];
}

Ответы (3 шт):

Автор решения: Mikhailo

Записывать - понятие не очень понятное. Но начнем.
Первое, мы придерживаемся стандарта, и никаких VLA.
Второе, мы рассматриваем встроенные многомерные массивы в С++, те, которые в памяти раполагаются одним блоком, а не динамически выделяемые.

Тогда: объявление массива.

type name[##][##]..[##]

Где ## — размерности массива, известные во время компиляции.

Массив может быть указан без первого размера, если он вычисляется из инициализатора. Например,

int m[][2] = {{4,5},{6,8}};

При передаче в функцию действуют те же правила - вы передаете аргумент так же, как и объявляете массив, и можете не указывать первую размерность. Например,

void f(int m[][5]);

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

→ Ссылка
Автор решения: AlexGlebe

Эта запись взята из C кода. И там чтобы просчитывать место памяти элементов нужно было указывать размерность массива, и можно было пропускать первую размерность.

void FuncArr(const int row, const int col,int arr[][col])

Но в C++ аргумент массива с плавающей размерностью запретили и нужно уже писать шаблон. Размерности массива уже надо передавать как аргумент шаблона.

template<size_t ROW,size_t COL>
void FuncArr(int ( & arr ) [ROW][COL]){
  ..
}
..
int arr[ROW][COL];
FuncArr(arr);
→ Ссылка
Автор решения: avp

Наверняка, это не ответ на вопрос, но представьте, что вы хотите написать функцию, которая опрерирует с массивами заранее не известной размерности.

Описать ее напрямую средствами языка не получится. Однако, все можно смоделировать (по сути, средствами интерпретации).

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

Например:

// returns pointer to multidimension array[upper][...]...[...][lower] item
// `arr`          pointer to the first item
// `dims`         number of dimensions
// `dsz[dims]`    number of array items in each dimension (from upper to lower)
// `indx[dims]`   indexes of given item
int *
get_pitmx (int *arr, int dims, int dsz[], int indx[])
{
  int sum = 0;

  for (int i = 0; i < dims - 1; i++)
    sum += (indx[i] * dsz[i + 1]);
  
  return arr + sum + indx[dims - 1];
}

Конечно, нулевой элемент массива dsz[] не используется, но я оставил его для того, чтобы этот массив было проще заполнять (или рассчитывать), глядя на описание многомерного массива в точке его определения.

Продемонстрировать, как это использовать на С++, можно таким примером:

int main () {

  // просто матрица из 4-х строк и 3-х столбцов
  int a2[4][3] = {{ 1,  2,  3},
                  {11, 12, 13},
                  {21, 22, 23},
                  {31, 32, 33}};
  // массив из 2-х таких матриц
  int a3[2][4][3];

  int ix[3] = {2, 2};         // массив индексов интересующего нас элемента
  int dsz[3] = {24, 12, 3};   // количество элементов в каждой размерности массива матриц (`a3`)
                              // 2 последних элемента в нем описывают количество элементов по размерностям в матрице `a2`

  int *p = get_pitmx ((int *)a2, 2,
                      dsz + 1,
                      ix);
  printf("a2[%d][%d] = %d\n", ix[0], ix[1], *p);


  for (int k = 0; k < 2; k++)
    for (int i = 0; i < 4; i++)
      for (int j = 0; j < 3; j++)
        a3[k][i][j] = k * 100 + a2[i][j];

  p = get_pitmx ((int *)a3, 3,
                 dsz,
                 (ix[0] = 1, ix[1] = 3, ix[2] = 1, ix));
  printf("a3[%d][%d][%d] = %d\n", ix[0], ix[1], ix[2], *p);
  
  return puts("End") == EOF;
}

(К сожалению, в С++ нельзя передавать адреса временных массивов, на чистом Си этот пример (но с созданием массива индксов прямо в вызове функции) выглядит получше)

→ Ссылка