【问题标题】:Manipulate multidimensional array in a function在函数中操作多维数组
【发布时间】:2013-06-01 09:19:04
【问题描述】:

我在这里读了很多东西并尝试了很多,但我找不到将多维数组传递给 C 中的函数、更改一些值并以某种方式返回新数组的方法。 找到一种方法将该数组进一步传递给另一个函数并执行相同的操作非常重要。

我想找到一种将数组传递给函数的方法。然后将它从第一个函数传递给第二个函数,在那里做一些事情(也许打印,也许改变值),然后再次将它用于第一个函数最后在 main 中使用该数组。

我最后一次尝试是:

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

}

来自here

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

【问题讨论】:

  • 你没有定义ROWS和COLUMNS吗?
  • @Lucas 不,我做了。我只是编辑问题
  • 在第二个示例中,您从未定义行和列的大小。此外,main 中的局部变量会影响全局定义。
  • @Lucas 问题已编辑..

标签: c arrays function multidimensional-array parameters


【解决方案1】:

对于你的二维数组,我会为它定义一个类型。

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

    }

【讨论】:

    【解决方案2】:

    要记住的几件事:

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

    2. [] 运算符可用于数组或指针类型的表达式; IOW,给定声明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] 怎么了?请记住,在将数组表达式作为参数传递时,数组表达式的类型从“T 的 N 元素数组”转换为“指向 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 );
      ...
    }
    

    foo 中对数组内容所做的任何更改都将反映在barmain 中。

    VLA 很有用,但也有其局限性。它们不能声明为static,也不能在函数之外定义。他们不能使用{} 风格的初始化语法。此外,从 2011 年标准开始,VLA 支持现在是可选,因此您不能依赖它们在任何地方都得到支持。

    如果您没有可用的 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 );
      }
    }
    

    这种方法的一个缺点是分配的内存不能保证是连续的(即,行在内存中不会相邻)。如果这很重要,您将不得不采用另一种方法。您无需单独分配行和列,而是将所有内容分配在一个块中,并手动映射数组索引:

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

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

    【讨论】:

      【解决方案3】:

      不完全确定,问题是什么,但这有效(并打印值“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;
      }
      

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

      【讨论】:

      • 如果我想将数组从函数传递到另一个函数等等怎么办?它的工作方式相同?
      • 数组作为指针传递。所以它们都指向同一个数组实例。
      • 称为引用传递。
      • @Lucas 所以你是说我应该将数组从第一个函数传递给第二个函数,就像我在开始时将它从 main 传递给第一个函数一样?
      【解决方案4】:

      将数组视为指向内存的指针会很有帮助。然后很容易将二维数组视为指向指针内存的指针(有点)

      这行不通

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

      但这对我来说效果很好

       1 #include <stdio.h>
       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<row;i++)
       11       for(j=0;j<col;j++)
       12         printf("%d  - ",arr[i][j]);
       13 
       14 
       15  }
      

      【讨论】:

      • 这不是回答我关于更改函数内数组的值并返回这些值的问题..
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-01-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-29
      相关资源
      最近更新 更多