Манипулировать multidimensional array в функции

Я прочитал много вещей здесь и пробовал много, но я не мог найти способ передать multidimensional array функции в C, изменить некоторые из значений и как-то вернуть новый массив. Важно найти способ передать этот массив дальше другой функции и сделать то же самое.

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

Моя последняя попытка:

void func(int multarray[][columns]){ multarray[0][0]=9; } int main(){ int rows; int columns; int multarray[rows][columns]; func(multarray); return 0; } 

Я также пробовал:

 void func(int multarray[rows][columns]){ multarray[0][0]=9; } int main(){ int rows; int columns; int multarray[rows][columns]; func(multarray); return 0; } 

Я также пробовал:

 int getid(int row, int x, int y) { return (row*x+y); } void printMatrix(int*arr, int row, int col) { for(int x = 0; x < row ; x++) { printf("\n"); for (int y = 0; y <col ; y++) { printf("%d ",arr[getid(row, x,y)]); } } } main() { int arr[2][2] = {11,12,21,22}; int row = 2, col = 2; printMatrix((int*)arr, row, col); } 

отсюда

Я также пытался использовать двойные указатели. Я также читал, что существует другой подход, если компилятор не поддерживает VLA. Я использую gnu.

Не совсем уверен, в чем проблема, но это работает (и печатает значение «9»):

 #include  #define ROWS 10 #define COLUMNS 10 void func2(int multarray[][COLUMNS]){ multarray[1][4]=10; } void func1(int multarray[][COLUMNS]){ multarray[0][3]=9; func2(multarray); } int main(){ int multarray[ROWS][COLUMNS]; func1(multarray); printf("%d\n", multarray[0][3]); printf("%d\n", multarray[1][4]); return 0; } 

Обратите внимание, что массив переходит в указатель при передаче функции.

Несколько вещей, чтобы помнить:

  1. Когда вы передаете выражение массива в качестве аргумента функции, оно будет преобразовано из выражения типа «N-element array of T » в «указатель на T », а значение выражения будет адресом первого элемент массива. Вызываемая функция получает значение указателя.

  2. Оператор [] может использоваться с выражениями типа массива или указателя; IOW, учитывая объявления int a[10]; int *p = a; int a[10]; int *p = a; , то p[i] и a[i] относятся к одному и тому же элементу.

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

Итак, для функции, которая управляет 2D VLA, вы должны написать что-то вроде

 void foo( size_t rows, size_t cols, int (*multiarray)[cols] ) // or multiarray[][cols] { size_t i, j; for ( i = 0; i < rows; i++ ) for ( j = 0; j < cols; j++ ) multiarray[i][j] = some_value(); } 

Что случилось с int (*multiarray)[cols] ? Помните, что при передаче выражения массива в качестве аргумента тип выражения массива преобразуется из «N-элементного массива T » в «указатель на T ». В этом случае T является « cols -element array of int », поэтому мы переходим от « rows -element array of cols -element aray от int » к «указателю на cols -element array of int ». В контексте объявления параметра функции T a[N] , T a[] и T *a все одинаковы; во всех трех случаях a объявляется как указатель на T Таким образом, int (*multiarray)[cols] эквивалентно int multiarray[][cols] , что эквивалентно int multiarray[rows][cols] . Я предпочитаю использовать первую форму, потому что она наиболее точно отражает ситуацию.

Если вы хотите передать этот массив в качестве аргумента другой функции, вы должны использовать тот же тип:

 void bar( size_t rows, size_t cols, int (*multiarray)[cols] ) { foo( rows, cols, multiarray ); } int main( void ) { size_t rows = 0; size_t cols = 0; // you must assign values to rows and cols before declaring a VLA with them rows = ...; cols = ...; int arr[rows][cols]; bar( rows, cols, arr ); ... } 

Любые изменения в содержимом массива, сделанные в foo будут отображаться в bar и в main .

ОЛА могут быть полезны, но у них есть свои ограничения. Они не могут быть объявлены static и не могут быть определены вне функции. Они не могут использовать синтаксис инициализации {} -style. Кроме того, поддержка VLA теперь является необязательной с 2011 года, поэтому вы не можете полагаться на то, что они поддерживаются повсюду.

Если у вас нет доступных VLA, и размер вашего массива неизвестен до запуска, вам придется использовать динамическое распределение памяти ( malloc или calloc ), а типы, которые вы передаете своим функциям, будут разными:

 void foo( size_t rows, size_t cols, int **multiarray ) { size_t i, j; for ( i = 0; i < rows; i++ ) for ( j = 0; j < cols; j++ ) multiarray[i][j] = some_value(); } void bar( size_t rows, size_t cols, int **multiarray ) { foo( rows, cols, multiarray ); } int main( void ) { size_t rows; size_t cols; int **multiarray = NULL; ... // get rows and cols // allocate memory for pointers to each row multiarray = malloc( sizeof *multiarray * rows ); if ( multiarray ) { size_t i; // allocate each row for ( i = 0; i < rows; i++ ) { multiarray[i] = malloc( sizeof *multiarray[i] * cols ); if ( !multiarray[i] ) break; } if ( i < rows ) { // malloc failed for one of the multiarray rows; we need to // free whatever memory has already been allocated and exit while ( i-- ) free( multiarray[i] ); free( multiarray ); exit(0); } } bar ( rows, cols, multiarray ); ... if ( multiarray ) { size_t i; for ( i = 0; i < rows; i++ ) free( multiarray[i] ); free( multiarray ); } } 

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

 void foo( size_t rows, size_t cols, int *fakemultiarray ) { size_t i, j; for ( i = 0; i < rows; i++ ) for ( j = 0; j < rows; j++ ) fakemultiarray[ i * rows + j ] = some_value(); } void bar( size_t rows, size_t cols, int *fakemultiarray ) { foo( rows, cols, fakemultiarray ); } int main( void ) { size_t rows; size_t cols; int *fakemultiarray = NULL; ... // get rows and cols fakemultiarray = malloc( sizeof *fakemultiarray * rows * cols ); if ( fakemultiarray ) bar( rows, cols, fakemultiarray ); ... free( fakemultiarray ); } 

В этом случае мы выделили один буфер, достаточно большой для всех элементов, но мы должны индексировать его как 1D-массив, вычисляя индекс как i * rows + j .

Для ваших 2-мерных массивов я бы определил для него тип.

 typedef int my2DArray_t[ROWS][COLUMNS]; 

Затем вы можете объявить переменные этого типа и указатели на них. Это облегчает передачу вещей.

 void someFuncOther (my2DArray_t *someArray) { /* Set some values in array */ (*someArray)[1][1] = 4; } void someFunc (my2DArray_t *someArray) { /* Set some values in array */ (*someArray)[1][0] = 7; /* Have someFuncOther do some more work */ someFuncOther (someArray); } int main (void) { /* This is the actual array */ my2DArray_t myArray; /* Set some values in array */ myArray[0][2] = 6; /* Have someFunc do some work on myArray by passing a pointer to it */ someFunc (&myArray); } 

Полезно рассматривать массивы как указатели на память. Тогда легко представить массив 2d как указатель на память указателей (kinda)

Это не сработает

  int arr[2][2] = {11,12,21,22}; //not going to work 

но это сработало отлично для меня

  1 #include  2 3 4 main() 5 { 6 int arr[2][2] = {{11,1},{2,21}}; 7 int row = 2, col = 2; 8 int i,j; 9 10 for(i=0;i 
  • Как преобразовать lambda в std :: функцию с помощью шаблонов
  • C Программирование: malloc () внутри другой функции
  • Где бы вы использовали функцию friend против статической функции-члена?
  • Как вернуть 2 значения из метода Java?
  • Что такое представитель underscore в Swift References?
  • Встроенная функция члена C ++ в файле .cpp
  • Можно ли определить более одной функции для каждого файла в MATLAB и получить доступ к ним из-за пределов этого файла?
  • Плагин jQuery: добавление функций обратного вызова
  • Нестационарный член как аргумент по умолчанию для функции нестатического члена
  • C ++: Аргумент «Передано по ссылке»
  • Функция R не возвращает значения
  • Interesting Posts
    Давайте будем гением компьютера.