Как передать 2D массив (матрицу) в функцию в C? - PullRequest
46 голосов
/ 12 октября 2010

Мне нужно сделать это, чтобы сохранить операции над матрицей.Значит ли это, что его нужно передать по ссылке?

Будет ли этого достаточно?

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

Ответы [ 5 ]

94 голосов
/ 12 октября 2010

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

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

3) Использовать одномерный массив и исправить индексы. Это можно использовать как со статически распределенными (фиксированного размера), так и с динамически размещаемыми массивами:

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

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

(См. srand() - зачем называть его только один раз? .)

10 голосов
/ 12 октября 2010

Я не знаю, что вы подразумеваете под «данные не теряются».Вот как вы передаете нормальный 2D-массив в функцию:

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

int main() {
  int somearr[M][N];
  ...
  myfunc(somearr);
  ...
}
2 голосов
/ 09 января 2019

Самый простой способ: передача двумерного массива переменной длины

Самым чистым методом для C & C ++ является: передать двумерный массив как одномерный массив, а затем использовать как 2D внутри функции.

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] = { {1, 2, 3}, {7, 8, 9} };
    func(2, 3, matrix[0]);

    return 0;
}
0 голосов
/ 12 сентября 2018

2D массив:

int sum(int array[][COLS], int rows)
{

}

3D массив:

int sum(int array[][B][C], int A)
{

}

4D массив:

int sum(int array[][B][C][D], int A)
{

}

и массив nD:

int sum(int ar[][B][C][D][E][F].....[N], int A)
{

}
0 голосов
/ 03 апреля 2017
     #include <iostream>
     using namespace std;

     void printarray(int *a, int c,int r)
     {
        for (int i = 0; i < r; i++)
        {
            for (int j = 0; j < c; j++)
            {
                cout << "\t" << *(a + i*c + j) << "\t";  // a is a pointer refer to a 2D array
            }
        cout << endl << "\n\n";
        }
     }

     int main()
     {
         int array[4][4] = 
         {{1 ,2 ,3 ,4 },
          {12,13,14,5 },
          {11,16,15,6 },
          {10,9 ,8 ,7 }};

          printarray((int*)array,4,4);
          // here I use print function but u can use any other useful function like 
          //setArray((int *) array,4,4);

        return 0;
    }
...