在函数中操作多维数组

Dch*_*ris 3 c arrays parameters function 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;
}
Run Code Online (Sandbox Code Playgroud)

我也试过这个:

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

int main(){
    int rows;
    int columns;
    int multarray[rows][columns];
    func(multarray);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我也试过这个:

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);

}
Run Code Online (Sandbox Code Playgroud)

这里开始

我也试过双指针.我还读到,如果编译器不支持VLA,则有不同的方法.我正在使用gnu.

Joh*_*ode 9

要记住几件事:

  1. 将数组表达式作为参数传递给函数时,它将从"N元素数组T" 类型的表达式转换为"指向T",并且表达式的值将是第一个元素的地址.数组.被调用的函数接收指针值.

  2. []操作员可以用数组或指针类型的表达式中使用; 督察,给出的声明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();
}
Run Code Online (Sandbox Code Playgroud)

怎么了int (*multiarray)[cols]?请记住,在将数组表达式作为参数传递时,数组表达式的类型将从"N元素数组T"转换为"指向T".在这种情况下,T是" cols中-元素阵int",让我们从"走出去rows的-元素阵列cols的-元素阿雷int为""指针cols-元素的数组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 );
  ...
}
Run Code Online (Sandbox Code Playgroud)

对数组内容的任何更改foo都将反映在bar和中main.

VLA可能很有用,但它们有其局限性.它们不能被声明static,也不能在函数之外定义.他们不能使用{}-style初始化语法.此外,VLA支持现在可选为2011标准的,所以你不能依靠他们到处都支持.

如果您没有可用的VLA并且直到运行时才知道您的数组大小,则必须使用动态内存分配(malloccalloc),并且传递给函数的类型将不同:

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 );
  }
}
Run Code Online (Sandbox Code Playgroud)

这种方法的一个缺点是分配的存储器不能保证是连续的(即,行在存储器中不相邻).如果重要的话,你将不得不采用另一种方法.您可以在一个块中分配所有内容,并手动映射数组索引,而不是分别分配行和列:

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 );
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,我们为所有元素分配了一个足够大的缓冲区,但是我们必须将它作为一维数组索引,将索引计算为i * rows + j.


Luc*_*cas 5

不完全确定,问题是什么,但这有效(并打印值"9"):

#include <stdio.h>

#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;
}
Run Code Online (Sandbox Code Playgroud)

请注意,数组在传递给函数时会衰减为指针.