Passing a 2D Array to a C++ Function

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

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?.)

Passing a 2D array to a C++ function

There are three ways to pass a 2D array to a function:

  1. The parameter is a 2D array

    int array[10][10];
    void passFunc(int a[][10])
    {
    // ...
    }
    passFunc(array);
  2. The parameter is an array containing pointers

    int *array[10];
    for(int i = 0; i < 10; i++)
    array[i] = new int[10];
    void passFunc(int *a[10]) //Array containing pointers
    {
    // ...
    }
    passFunc(array);
  3. The parameter is a pointer to a pointer

    int **array;
    array = new int *[10];
    for(int i = 0; i <10; i++)
    array[i] = new int[10];
    void passFunc(int **a)
    {
    // ...
    }
    passFunc(array);

Passing 2D array by reference to function

The problem is that the methods:

void input(int*, int*);
void add(int*, int*, int*);
void display(int*);

expected a pointer, however you are passing to them 2D arrays (statically allocated), namely int a[3][3], b[3][3], sum[3][3];. Therefore, as already pointed out in the comments, those 2D arrays will be converted to 'int (*)[3]'. Consequently, you need to adapt the signature of your methods to:

void input(int [][3], int [][3]);
void add(int [][3], int [][3], int [][3]);
void display(int [][3]);

and

void input(int a[][3], int b[][3]){
// the code
}

void add(int a [][3], int b [][3], int sum [][3]){
// the code
}

void display(int sum [][3]){
// the code
}

Alternatively, if you want to keep the int* as parameter then what you can do is to allocate the matrix as a single array and adapt your code accordingly

passing 2d array after specific i index to function so just pass specific one d from 2d array

For starters there is no sense to output integers like 1, 2, 3 as characters using the conversion specifier %c.

Either output them as indeed integers using the conversion specifier %d or convert them to characters using expressions like arr[i] + '0' or initialize the source array using characters as '1', '2', '3'.

For this call

print(3,arr+1);

the compiler will issue a message because the type of the argument expression arr + 1 char ( * )[3] differs from the type of the corresponding function parameter char *.

You need to write either

print(3,arr[1]);

or

print(3, *( arr + 1 ) );

In this case the expressions arr[1] and *( arr + 1 ) yield a character array of the type char[3] that is implicitly converted to pointer to its first element of the type char *.

Why I got a warning when I pass 2D array in function with constant parameter whilst in 1D everything is normal?

This is a defect in the C standard; a pointer to an array of char is not compatible with a pointer to an array of const char and may not be passed (with defined behavior) as an argument for a parameter of type pointer to an array of const char.

Note that after the automatic conversion of arrays, print_w(words) passes a pointer to an array to print_w, not an array of arrays, and, after the automatic adjustment of array parameters, void print_w(const char x[W] [N+1]) declares printString to have a parameter of type pointer to array, not array of array. So we are concerned with the rules for pointers to arrays.

For char (*)[N+1] and const char (*)[N+1], we first consider whether these pointer types are compatible. Per C 2018 6.7.6.1 2, for two pointer types to be compatible, they must point to compatible types.

They point to arrays, so we look 6.7.6.2 6, which says, for two array types to be compatible, both shall have compatible element types.

For the elements, we look to 6.7.3 11, which says, for two qualified types to be compatible, both shall have the identically qualified version of a compatible type. char and const char are not identically qualified, so they are not compatible, so the array types are not compatible, so the pointer types are not compatible.

Function calls allow passing arguments for parameters if an assignment to the parameter type is allowed, per C 6.5.2.2 2. Per 6.5.16.1 1, assignment allows “adding” a qualifier to the pointed-to type. For example, a pointer to char can be assigned to a pointer to const char. This is why the void printString(const char []) code does not yield an error or warning message. However, the rules do not allow adding a qualifier deeper in the type. So a pointer to an array of char cannot be assigned to a pointer to an array of const char.

This is a defect in the C standard. There is some work in the C committee to fix this. In draft N2731, 6.2.5 28 says “… An array and its element type are always considered to be identically qualified.…” This could make the interpretation of the assignment that a pointer to an array of char is being assigned to a pointer to a const-qualified array of char, which would be allowed.

In the meantime, when you use the -pedantic switch, GCC is pedantic. One remedy is not to ask it to be pedantic. Another is to use an explicit cast. Another is to use Clang or another compiler.



Related Topics



Leave a reply



Submit