3

我在这里读了很多东西并尝试了很多,但我找不到将多维数组传递给 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。

4

4 回答 4

9

要记住的几件事:

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

  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]?请记住,在将数组表达式作为参数传递时,数组表达式的类型从“N-element array of T”转换为“pointer to T”。在本例中,T是“ cols-element array of int”,所以我们从“ -element rowsarray of cols-element aray of int”变为“pointer to - colselement array of int”。在函数参数声明的上下文中T a[N]T a[]、 和T *a都是相同的;在所有三种情况下,都a被声明为指向. TSoint (*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

VLA 可能很有用,但它们也有其局限性。它们不能被声明static,也不能在函数之外定义。他们不能使用{}-style 初始化语法。此外,从 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.

于 2013-06-05T16:29:00.317 回答
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;
}

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

于 2013-06-05T15:38:42.857 回答
3

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

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

    }
于 2013-06-05T16:13:59.203 回答
0

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

这行不通

 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  }
于 2013-06-05T15:40:32.727 回答