Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to pass 2D array (matrix) in a function in C?

I need to do this to persist operations on the matrix as well. Does that mean that it needs to be passed by reference?

Will this suffice?

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

like image 847
Shweta Avatar asked Oct 12 '10 03:10

Shweta


People also ask

How do you pass a 2D array to a function without size?

With a 2D array like int a[5][3] , you have 5 times 3 int s in a row, all in all 15 int s. For accessing an element, the compiler will compute the offset for you, so if you write e.g. a[2][2] , this is the 2*3 + 2 th element (there are two rows of 3 columns to skip for the beginning of the third row).

How can we pass array to function in C?

To pass an entire array to a function, only the name of the array is passed as an argument. result = calculateSum(num); However, notice the use of [] in the function definition. This informs the compiler that you are passing a one-dimensional array to the function.

Can we allocate a 2 dimensional array dynamically?

A 2D array can be dynamically allocated in C using a single pointer. This means that a memory block of size row*column*dataTypeSize is allocated using malloc and pointer arithmetic can be used to access the matrix elements.


2 Answers

C does not really have multi-dimensional arrays, but there are several ways to simulate them. The way to pass such arrays to a function depends on the way used to simulate the multiple dimensions:

1) Use an array of arrays. This can only be used if your array bounds are fully determined at compile time, or if your compiler supports VLA's:

#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) Use a (dynamically allocated) array of pointers to (dynamically allocated) arrays. This is used mostly when the array bounds are not known until runtime.

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) Use a 1-dimensional array and fixup the indices. This can be used with both statically allocated (fixed-size) and dynamically allocated arrays:

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) Use a dynamically allocated VLA. One advantage of this over option 2 is that there is a single memory allocation; another is that less memory is needed because the array of pointers is not required.

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

(See srand() — why call it only once?.)

like image 93
Bart van Ingen Schenau Avatar answered Sep 21 '22 09:09

Bart van Ingen Schenau


Easiest Way in Passing A Variable-Length 2D Array

Most clean technique for both C & C++ is: pass 2D array like a 1D array, then use as 2D inside the function.

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

Internally, no matter how many dimensions an array has, C/C++ always maintains a 1D array. And so, we can pass any multi-dimensional array like this.

like image 22
Minhas Kamal Avatar answered Sep 22 '22 09:09

Minhas Kamal