如何在C中的函数中传递2D数组(矩阵)?

Shw*_*eta 50 c parameter-passing multidimensional-array

我需要这样做才能在矩阵上持续操作.这是否意味着它需要通过引用传递?

这还够吗?

void operate_on_matrix(char matrix[][20]);

Bar*_*nau 99

C实际上没有多维数组,但有几种方法可以模拟它们.将此类数组传递给函数的方法取决于模拟多个维度的方式:

1)使用数组数组.只有在编译时完全确定数组边界,或者编译器支持VLA时,才能使用此方法:

#define ROWS 4
#define COLS 5

void func(int array[ROWS][COLS])
{
  int i, j;

  for (i=0; i<ROWS; i++)
  {
    for (j=0; j<COLS; j++)
    {
      array[i][j] = i*j;
    }
  }
}

void func_vla(int rows, int cols, int array[rows][cols])
{
  int i, j;

  for (i=0; i<rows; i++)
  {
    for (j=0; j<cols; j++)
    {
      array[i][j] = i*j;
    }
  }
}

int main()
{
  int x[ROWS][COLS];

  func(x);
  func_vla(ROWS, COLS, x);
}
Run Code Online (Sandbox Code Playgroud)

2)使用(动态分配的)指针数组(动态分配)数组.这主要用于直到运行时才知道数组边界的情况.

void func(int** array, int rows, int cols)
{
  int i, j;

  for (i=0; i<rows; i++)
  {
    for (j=0; j<cols; j++)
    {
      array[i][j] = i*j;
    }
  }
}

int main()
{
  int rows, cols, i;
  int **x;

  /* obtain values for rows & cols */

  /* allocate the array */
  x = malloc(rows * sizeof *x);
  for (i=0; i<rows; i++)
  {
    x[i] = malloc(cols * sizeof *x[i]);
  }

  /* use the array */
  func(x, rows, cols);

  /* deallocate the array */
  for (i=0; i<rows; i++)
  {
    free(x[i]);
  }
  free(x);
}
Run Code Online (Sandbox Code Playgroud)

3)使用1维数组并修正索引.这可以与静态分配(固定大小)和动态分配的数组一起使用:

void func(int* array, int rows, int cols)
{
  int i, j;

  for (i=0; i<rows; i++)
  {
    for (j=0; j<cols; j++)
    {
      array[i*cols+j]=i*j;
    }
  }
}

int main()
{
  int rows, cols;
  int *x;

  /* obtain values for rows & cols */

  /* allocate the array */
  x = malloc(rows * cols * sizeof *x);

  /* use the array */
  func(x, rows, cols);

  /* deallocate the array */
  free(x);
}
Run Code Online (Sandbox Code Playgroud)

4)使用动态分配的VLA.这超过选项2的一个优点是存在单个存储器分配; 另一个是需要更少的内存,因为不需要指针数组.

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

extern void func_vla(int rows, int cols, int array[rows][cols]);
extern void get_rows_cols(int *rows, int *cols);
extern void dump_array(const char *tag, int rows, int cols, int array[rows][cols]);

void func_vla(int rows, int cols, int array[rows][cols])
{
    for (int i = 0; i < rows; i++)
    {
        for (int j = 0; j < cols; j++)
        {
            array[i][j] = (i + 1) * (j + 1);
        }
    }
}

int main(void)
{
    int rows, cols;

    get_rows_cols(&rows, &cols);

    int (*array)[cols] = malloc(rows * cols * sizeof(array[0][0]));
    /* error check omitted */

    func_vla(rows, cols, array);
    dump_array("After initialization", rows, cols, array);

    free(array);
    return 0;
}

void dump_array(const char *tag, int rows, int cols, int array[rows][cols])
{
    printf("%s (%dx%d):\n", tag, rows, cols);
    for (int i = 0; i < rows; i++)
    {
        for (int j = 0; j < cols; j++)
            printf("%4d", array[i][j]);
        putchar('\n');
    }
}

void get_rows_cols(int *rows, int *cols)
{
    srand(time(0));           // Only acceptable because it is called once
    *rows = 5 + rand() % 10;
    *cols = 3 + rand() % 12;
}
Run Code Online (Sandbox Code Playgroud)

(参见srand()- 为什么只召唤一次?.)

  • `void func_vla(int array [rows] [cols],int rows,int cols)`应该是`void func_vla(int rows,int cols,int array [rows] [cols])` (5认同)

Min*_*mal 14

传递可变长度二维数组的最简单方法

C 和 C++ 最干净的技术是:像一维数组一样传递二维数组,然后在函数内部用作二维数组。

#include <stdio.h>

void func(int row, int col, int* matrix){
    int i, j;
    for(i=0; i<row; i++){
        for(j=0; j<col; j++){
            printf("%d ", *(matrix + i*col + j)); // or better: printf("%d ", *matrix++);
        }
        printf("\n");
    }
}

int main(){
    int matrix[2][3] = { {0, 1, 2}, {3, 4, 5} };
    func(2, 3, matrix[0]);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

在内部,无论数组有多少维,C/C++ 始终维护一个一维数组。因此,我们可以像这样传递任何多维数组。


cas*_*nca 10

我不知道你的意思是"数据不要丢失".以下是将普通2D数组传递给函数的方法:

void myfunc(int arr[M][N]) { // M is optional, but N is required
  ..
}

int main() {
  int somearr[M][N];
  ...
  myfunc(somearr);
  ...
}
Run Code Online (Sandbox Code Playgroud)

  • 随机事实:N是必需的原因是因为计算机需要知道为每个"行"增加指针的距离.实际上,除了第一个尺寸之外的所有尺寸都是必要的.C将数组存储为内存块,没有分隔符. (18认同)
  • @ChristianMann 相反,数组语法之所以有效,是因为编译器将参数中的数组声明调整为指向第一个元素的指针,在本例中为 `int (*)[N]`。这也是为什么必须提供除最外层之外的所有维度的原因——数组只衰减一次。这与“计算机需要知道的”完全无关 - 胡说八道。将它与一维情况进行比较:`void func (int [n])`,它被调整为 `void func (int*)` 并且所有的大小信息都丢失了——“计算机”不知道一件事,编译器不在乎。 (2认同)