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:
The parameter is a 2D array
int array[10][10];
void passFunc(int a[][10])
{
// ...
}
passFunc(array);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);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
Invalid Operands Error for Addition and Integer Division
C++: How to Iterate Over Each Char in a String
Forcing the Qt Gui to Update Before Entering a Separate Function
When to Use Virtual Destructors
How to Print a Double Value With Full Precision Using Cout
Why Is Integer Assignment on a Naturally Aligned Variable Atomic on X86
Why Is Volatile Not Considered Useful in Multithreaded C or C++ Programming
What Are the Evaluation Order Guarantees Introduced by C++17
Why Can't the Switch Statement Be Applied on Strings
Why Should the Implementation and the Declaration of a Template Class Be in the Same Header File
How to Align Text to the Right Using Cout
How to Add a Background Image to the Qmainwindow
Automatically Refreshing a Qtableview When Data Changed
Difference Between Const Int*, Const Int * Const, and Int Const *
How to Detect Unsigned Integer Overflow
Easiest Way to Convert Int to String in C++
What Are the Advantages of List Initialization (Using Curly Braces)