передача статически выделенных 2D-массивов в качестве аргументов функции в C

Рассмотрим этот код:


#include <stdio.h>
#define N 5
void printMatrix(int (*matrix)[N],int n)
{
   int i,j;
   for(i=0;i<n;i++){
      for(j=0;j<n;j++)
        printf("%d",matrix[i][j]);
     printf("\n");
   }
}
int main()
{
   int R[N][N]={{1,2,3},{4,5,6},{7,8,9}};
   printMatrix(R,3);
}

Это прекрасно работает, как и ожидалось.
Теперь я подумал написать функции, работающие с 2D-матрицами, в отдельном исходном файле и связать их там, где это необходимо.
Но тут я столкнулся с проблемой, как в функции printMatrix, размер массива int, на который указывает matrix (т.е. N), требуется во время компиляции. Итак, мои функции не будут работать в других случаях, когда размер другой.

Итак, как с этим справиться?
Динамические массивы — это решение, но я хочу знать, можно ли это сделать со статическими массивами.


person sud03r    schedule 16.02.2010    source источник


Ответы (5)


Вы не можете использовать встроенный тип 2D-массива, если оба размера неизвестны во время компиляции. Встроенный двумерный массив должен иметь хотя бы один из двух размеров, известных во время компиляции.

Если оба размера являются значениями времени выполнения, у вас нет другого выбора, кроме как использовать «ручную» реализацию 2D-массива, например, массив указателей на массивы. В этом случае объявление функции может выглядеть следующим образом (две альтернативные эквивалентные формы)

void printMatrix(int *const *matrix, int n, int m);
void printMatrix(int *const matrix[], int n, int m);

Для доступа к элементам массива вы по-прежнему можете использовать «традиционный» синтаксис

matrix[i][j]

Сам массив будет создан следующим образом (простой пример)

int row0[] = { 1, 2, 3 };
int row1[] = { 4, 5, 6 };

int *matrix[2];
matrix[0] = row0;
matrix[1] = row1;

printMatrix(matrix, 2, 3);

Но если у вас уже есть матрица, реализованная в виде встроенного двумерного массива

int matrix[2][3] = { ... };

затем просто для того, чтобы передать его вышеуказанной функции, вы можете «преобразовать» его в вышеуказанную форму, используя дополнительный временный массив «указатель строки»

int *rows[2];
rows[0] = matrix[0];
rows[1] = matrix[1];

printMatrix(rows, 2, 3);
person AnT    schedule 16.02.2010
comment
@ Брайан Р. Бонди: это была опечатка. Я имел в виду int *rows[2]. Исправлено. Спасибо. - person AnT; 16.02.2010

Напишите себе макрос:

#define MAT(i,j) matrix[i*n + j];

и объявите «матрицу» как простой указатель на «int».

person Steve Emmerson    schedule 16.02.2010

Вычислите индекс массива самостоятельно. Это будет обрабатывать произвольный двумерный массив, например:

void printMatrix(int *matrix,int n, int m)
{
   int i,j;
   for(i=0;i<n;i++){
    for(j=0;j<m;j++)
     printf("%d",matrix[m * i + j]);
   printf("\n");
   }
}
person Richard Pennington    schedule 16.02.2010

Не пытайтесь передать его как двумерный массив; передайте указатель на первый элемент, затем вычислите смещения вручную:

void printMatrix(int *a, size_t m, size_t n)
{
  size_t i,j;
  for (i = 0; i < m; i++)
  {
    for (j = 0; j < n; j++)
    {
      printf("a[%lu][%lu] = %d\n",
       (unsigned long) i, 
       (unsigned long) j, 
       a[i*n+j]); // treat a as 1-d array, compute offset manually
    }
  }
}

int main(void)
{
  int arr[5][4];
  ...
  printMatrix(&arr[0][0], 5, 4);
  ...
}

Конечно, это будет работать только для смежных массивов.

person John Bode    schedule 16.02.2010

Хотя синтаксис не совсем такой же, но это также немного работает:


#include <stdio.h>
#define N 5
void printMatrix(int* row,int n,int sz)
{
   int i,j;
   int *currRow;
   for(i=0;i<n;i++){
      currRow = row+i*sz;
      for(j=0;j<n;j++)
        printf("%d",currRow[j]);
     printf("\n");
   }
}
int main()
{
   int R[N][N]={{1,2,3},{4,5,6},{7,8,9}};
   printMatrix(R[0],3,sizeof(R[0])/sizeof(int));
}


person sud03r    schedule 16.02.2010