Перейти к содержимому

Как передать многомерный массив в функцию c

  • автор:

Как правильно передать двумерный массив в функцию?

но если указать вместо size, конкретную цифру то все сработает.

void foo(int arr[][5]) < . >int arr[5][5] = <>;

Как в первом случае отправить массив в функцию ? Подскажите самый оптимальный вариант.

  • Вопрос задан более трёх лет назад
  • 9141 просмотр

Решения вопроса 3

myjcom

Roman @myjcom Куратор тега C++
const int size
Массив не передается. Передается указатель. Даже если вы пишете a[][size]
Ответ написан более трёх лет назад
Нравится 1 2 комментария

myjcom

Roman @myjcom Куратор тега C++
Размер массива должен быть известен на этапе компиляции.

myjcom

Roman @myjcom Куратор тега C++
int sum; неинициализированная переменная

#include template int foo(int (&matrix)[ColumnCount][RowCount]) < int r = 0; for(auto& row: matrix)< for(auto& x: row) r += x; >return r; > int bar()< int matrix [][2] = , , >; return foo(matrix); >

С-массивы в функции можно передавать только по ссылке. Или преобразовать в массив указателей.

Вообще, для передачи С-массивов придуман std::array , но двумерный C-массив нельзя напрямую привести к std::array, N> . Но можно изначально работать с std::array :

template int foo(std::array, ColumnCount>& matrix) < int r = 0; for(auto& row: matrix)< for(auto& x: row) r += x; >return r; > int bar()< std::array, 3> matrix = , , >>; return foo(matrix); >

Ответ написан более трёх лет назад
Нравится 1
Developer, ex-admin

Если вы изучаете С++, то лучше использовать классы стандартной библиотеки для массивов. В функцию передаете ссылку на класс.
В чистом Си передается просто указатель и размер в отдельном параметре (или 2 размера для двумерного массива).
Сам двумерный массив может быть представлен в двух вариантах:
1.Как массив указателей, где каждый указатель представляет собой одномерный массив. Нужно отдельно выделять память для массива указателей и для каждого одномерного подмассива и аналогично освобождать. В этом случае возможна операция индексации обоих измерений массива, при этом массив указателей и каждый подмассив могут находится в разных участках памяти.

void foo(int ** arr, int N, int M) < . >int main() < int N = 10; // первое измерение массива int M = 20; // второе измерение массива int ** arr = new int * [N]; for(int i = 0; i < M; ++i) < arr[i] = new int[M]; >. foo(arr, N, M); . // Тут освобождение массива аналогично выделению в обратном порядке >

2.Как одномерный массив размерностью N * M. В этом случае память под массив выделяется и освобождается вся оптом одним куском, но операция индексации первых размерностей не возможна. Но можно легко переходить от двумерного массива к одномерному, сразу вычислять нужный индекс или просто перемещаться по элементам массива с помощью временного указателя.

void foo(int * arr, size_t N, size_t M) < . >int main() < int N = 10; // первое измерение массива int M = 20; // второе измерение массива int * arr = new int * [N*M]; int * arrcur = arr; // временный указатель для обхода массива int * arrone = arr; // вариант с переходом к одномерному массиву for(int i = 0; i < N; ++i) < for(int j = 0; j < M; ++j) < // Вариант с вычислением адреса текущего элемента по индексам *(arr + i * M + j) = rand() % 10; // вычисление нужного индекса на месте // Вариант с обходом массива с помощью временного указателя *arrcur = rand() % 10; ++arrcur; // переход к следующему элементу // Вариант с переходом к одномерному массиву arrone[j] = rand() % 10; >arrone += M; > . foo(arr, N, M); . delete[] arr; >

Как передать многомерный массив в функцию c

Скачай курс
в приложении

Перейти в приложение
Открыть мобильную версию сайта

© 2013 — 2023. Stepik

Наши условия использования и конфиденциальности

Get it on Google Play

Public user contributions licensed under cc-wiki license with attribution required

Передать двумерный статический массив в функцию

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

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

void f( int a[], size_t m, size_t n ); //. int A[3][4]; f( reinterpret_cast( A ), 3, 4 ); 

Вот демонстрационная программа

#include #include void f( int a[], size_t m, size_t n ) < for ( size_t i = 0; i < m; i++ ) < for ( size_t j = 0; j < n; j++ ) a[i * n + j ] = i * n + j; >> int main() < const size_t M = 3; const size_t N = 4; int a[M][N]; f( reinterpret_cast( a ), M, N ); for ( size_t i = 0; i < M; i++ ) < for ( size_t j = 0; j < N; j++ ) std::cout return 0; > 

Ее вывод на консоль

 0 1 2 3 4 5 6 7 8 9 10 11 

Если же писать программу на C, а не на C++, то там есть массивы переменной длины, и поэтому вам было бы проще.

В C++ для этих целей лучше использовать стандартный класс std::vector

std::vector> v( 3, std::vector( 4 ) ); 

Что касается вашего вопроса

2)Статические 2D массивы хранятся в памяти линейно. Динамические хранятся тоже линейно или нет?

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

int ( *a )[4] = new int[3][4]; 

А что касается этого вопроса

3)Какую связь имеет статический 2D массив с указателями?

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

Отслеживать
ответ дан 6 ноя 2015 в 19:03
Vlad from Moscow Vlad from Moscow
44.8k 3 3 золотых знака 38 38 серебряных знаков 89 89 бронзовых знаков
А как сделать эту функцию универсальнее, чтобы она принимала любые A[x][y] ?
6 ноя 2015 в 19:08

@neko69 Что значит «любые»? Если любые двумерные массивы с любыми значениями размерностей, то сделайте ее шаблонной.

6 ноя 2015 в 19:10
Шаблонная, в смысле template ? Без этого нельзя?
6 ноя 2015 в 19:12
@neko69 Если вы хотите иметь дело именно с двумерными массивами, то без этого не обойтись.
6 ноя 2015 в 19:13
@neko69 Смотрите мой обновленный ответ.
6 ноя 2015 в 19:17

В gcc сделать это совсем просто.

Вы можете передавать в функцию размерности матрицы (достаточно только «низших») и обращаться к элементам по индексам естестственным образом. Например:

void func (int n_lines, int n_columns, int array[][n_columns])

К сожалению g++ (и c++) не поддерживает такую передачу матриц в функцию. Поэтому проще всего (обладая знанием, что все элементы матрицы располагаются в памяти последовательно, сначала первая строка, за ней вторая и т.д.) передать в функцию адрес первого элемента матрицы, а в функции рассматривать ее как одномерный массив.
Естественно, пересчитывать индексы придется самому.

Вот пример файла, в котором представлены обе версии программы и результаты его запуска:

avp@avp-ubu1:hashcode$ cat c1.c #include #ifdef __cplusplus #include #endif static int aa[4][3] = < , , , >; #ifdef __cplusplus void func_matrix (int n, int m, int *x) < x[0] = x[(n - 1) * m + m - 1]; for (int i = 0; i < n; i++) for (int j = 0; j < m || !puts(""); j++) std::cout #else void func_matrix (int n, int m, int x[n][m]) < int i, j; x[0][0] = x[n - 1][m - 1]; for (i = 0; i < n; i++) for (j = 0; j < m || !puts(""); j++) printf("%d ", x[i][j]); >#endif int main (int ac, char *av[]) < #ifdef __cplusplus func_matrix(4, 3, &aa[0][0]); #else func_matrix(4, 3, aa); #endif >avp@avp-ubu1:hashcode$ gcc c1.c && ./a.out 43 12 13 21 22 23 31 32 33 41 42 43 avp@avp-ubu1:hashcode$ g++ c1.c && ./a.out 43 12 13 21 22 23 31 32 33 41 42 43 avp@avp-ubu1:hashcode$ 

Если вопросы еще остались, задавайте.

UPD

Вот вариант с указателями на строки «плотной» матрицы.

Берем статическую матрицу, делаем для нее массив указателей, передаем его в функцию транспонирования, которая делает в динамической памяти «плотную» транспонированную матрицу и возвращает новый массив указателей на ее строки.

#include #include int ** make_lines_ptrs (int *mx, int a, int b) < int **p = (int **)malloc(a * sizeof(int *)); for (int i = 0; i < a; i++) p[i] = mx + i * b; return p; >int ** transp (const int * const * m, int a, int b) < int *mx = (int *)malloc(a * b * sizeof(int)); for (int i = 0; i < a; i++) for (int j = 0; j < b; j++) mx[j * a + i] = m[i][j]; return make_lines_ptrs(mx, b, a); >void pri_mx (const int * const * m, int a, int b) < for (int i = 0; i < a; i++) for (int j = 0; j < b || !puts(""); j++) printf("%d ", m[i][j]); >static int aa[4][3] = < , , , >; int main (int ac, char *av[])

Ну, память перед выходом Вы уж сами освободите?

14 Лекция. Передача двумерного массива в качестве параметра функции (продолжение). Двумерные массивы в куче (обобщение).

Передача двумерного массива в качестве параметра функции (продолжение).

В предыдущих примерах основной недостаток — наличие глобальных переменных.

Избавиться от них можно если передавать в параметры функции не массив а только указатель.

Если убрать количество строк n_g компиляция программы пройдет успешно.

Пример: Передача двумерного массива в качестве параметра функции (в двух файлах).

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
#include #include #include "sum_array.h" int main ()  static int n=2, m=3; int sum_a; int array[n_g][m_g] = 1,4,5,3>,4,5,6,7>>; sum_a = sum_array(array,n,m); sum_a = sum_array(array,n_g,m_g); srand((unsigned)time(NULL)); for (int i=0; in; i++)  for (int j=0; jm; j++)  array[i][j]=1+rand()%8; > > sum_a = sum_array(array,n,m); sum_a = sum_array(array,n_g,m_g); > 

Пример: Файл (sum_array.h) с функцией «sum_array».

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
const int n_g =3; const int m_g =4; int sum_array (int array[][m_g], int n, int m)  int sum =0; for (int i=0; in; i++)  for (int j=0; jm; j++)  sum = sum + array[i][j]; std::cout  [i][j]  <" "; > std::cout  <"\n"; > std::cout  <"Сумма элементов массива sum color: #000080;">  <"\n"; return sum; >

Если убрать количество элементов в строке m_g, произойдет ошибка компиляции.

Т.к. строка является элементов одномерного массива, а размер элемента массива должен быть известен.

  1. замена многомерного массива одномерным и имитация внутри функции доступа к двумерному массиву,
  2. использование одномерного массива указателей на одномерные массивы (строки).

Пример: Передача двумерного массива в качестве параметра функции (в двух файлах).

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
#include #include #include "sum_array.h" int main ()  const int n=3, m=4; int sum_a; int array[n][m] = 1,4,5,3>,4,5,6,7>>; int *p[n]; for (int i=0; in; i++)  p[i] = array[i]; > sum_a = sum_array(p,n,m); srand((unsigned)time(NULL)); for (int i=0; in; i++)  for (int j=0; jm; j++)  array[i][j]=1+rand()%8; > > sum_a = sum_array(p,n,m); > 

Пример: Файл (sum_array.h) с функцией «sum_array».

1 2 3 4 5 6 7 8 9 10 11 12 13
int sum_array (int **mas, int n, int m)  int sum =0; for (int i=0; in; i++)  for (int j=0; jm; j++)  sum = sum + mas[i][j]; std::cout  [i][j]  <" "; > std::cout  <"\n"; > std::cout  <"Сумма элементов массива sum color: #000080;">  <"\n"; return sum; >

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

Двумерные массивы в куче (обобщение)

Создадим стандартные функции для работы с массивами в куче:

mem_new — выделение памяти в куче для массива
mem_del — освобождение памяти в куче для массива
add_array — заполнение массива
out_array — вывод массива

Пример: Файл (mem_new.h) с функцией «mem_new».

1 2 3 4 5 6 7 8 9
//Функция выделения памяти в куче для двухмерного массива void mem_new (int **&p, int n)  p = new int *[n]; for (int i=0; in; i++)  p[i] = new int [n]; > >

Пример: Файл (mem_del.h) с функцией «mem_del».

1 2 3 4 5 6 7 8 9
// Функция освобождения памяти void mem_del(int **p, int n)  for (int i=0;in; i++) delete [] p[i]; > delete [] p; >

Пример: Файл (add_array.h) с функцией «add_array».

1 2 3 4 5 6 7 8 9 10
// Функция заполнения массива случайными числами void add_array(int **p, int n)  srand((unsigned)time(NULL)); for (int i=0; in; i++)  for (int j=0; jn; j++)  p[i][j] = 1 + rand()%9; > > >

Пример: Файл (out_ar)(color: #0000ff;(color: #800080;ray.h) с функцией «out_array».

1 2 3 4 5 6 7 8 9 10 11
//Функция вывода матрицы на консоль void out_array(int **p, int n)  for (int i=0; in; i++)  for (int j=0; jn; j++)  std::cout [i][j] <" "; > std::cout  <"\n"; > >

Пример: Файл (main.cpp) с функцией «main».

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
#include #include #include #include "mem_new.h" #include "mem_del.h" #include "add_array.h" #include "out_array.h" int main ()  int n; std::cout  <"Введите размер матрици color: #008080;">; std::cin >> n; int **p; mem_new(p,n); add_array(p,n); out_array(p,n); mem_del(p,n); >

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *