Манипулировать multidimensional array в функции
Я прочитал много вещей здесь и пробовал много, но я не мог найти способ передать multidimensional array функции в C, изменить некоторые из значений и как-то вернуть новый массив. Важно найти способ передать этот массив дальше другой функции и сделать то же самое.
Я хотел бы найти способ передать массив функции. Затем передайте ее от первой функции ко второй, сделайте что-нибудь (возможно, напечатайте, возможно, измените значения), затем снова используйте ее для первой функции и, наконец, используйте этот массив в основном.
Моя последняя попытка:
- jQuery's .click - передать параметры пользователю
- Подавление вывода windows команды функции
- Должен ли я использовать спецификатор исключения в C ++?
- Вызов пользовательской функции GAS из внешнего URL-адреса
- Когда перегружать Comma Operator?
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.
- Можно ли задать аргумент по умолчанию из предыдущего аргумента?
- Разница между методами и функциями, в Python по сравнению с C ++
- Возврат указателя на автоматическую переменную
- Различия в использовании функций «const cv :: Mat &», «cv :: Mat &», «cv :: Mat» или «const cv :: Mat» как параметры функции?
- Static vs функции / переменные classа в classах Swift?
- Передача функции в качестве параметра в java
- dplyr: «Ошибка в n (): функция не должна вызываться напрямую»
- В объявлении функции C, что делает «...» как последний параметр?
Не совсем уверен, в чем проблема, но это работает (и печатает значение «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; }
Обратите внимание, что массив переходит в указатель при передаче функции.
Несколько вещей, чтобы помнить:
-
Когда вы передаете выражение массива в качестве аргумента функции, оно будет преобразовано из выражения типа «N-element array of
T
» в «указатель наT
», а значение выражения будет адресом первого элемент массива. Вызываемая функция получает значение указателя. -
Оператор
[]
может использоваться с выражениями типа массива или указателя; IOW, учитывая объявленияint a[10]; int *p = a;
int a[10]; int *p = a;
, тоp[i]
иa[i]
относятся к одному и тому же элементу. -
При объявлении функции, которая принимает 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