How to pass a multidimensional array to a function in C and C++
#include<stdio.h>
void print(int *arr[], int s1, int s2) {
int i, j;
for(i = 0; i<s1; i++)
for(j = 0; j<s2; j++)
printf("%d, ", *((arr+i)+j));
}
int main() {
int a[4][4] = {{0}};
print(a,4,4);
}
This works in C, but not in C++.
error:
cannot convert `int (*)[4]' to `int**' for argument `1' to
`void print(int**, int, int)'
Why does it not work in C++? What change is needed to be made?
This code will not work in either C or C++. An array of type int[4][4]
is not convertible to a pointer of type int **
(which is what int *arr[]
stands for in parameter declaration). If you managed to compile it in C, it is simply because you probably ignored a C compiler warning of basically the same format as the error message you got from C++ compiler. (Sometimes C compilers issue warnings for what is essentially an error.)
So, again, don't make assertions that are not true. This code does not work in C. In order to convert a built-in 2D array into a int **
pointer you can use a technique like this one
Converting multidimensional arrays to pointers in c++
(See the accepted answer. The problem is exactly the same.)
EDIT: The code appears to work in C because another bug in the printing code is masquerading the effects of the bug in array passing. In order to properly access an element of an int **
pseudo-array, you have to use expression *(*(arr + i) + j)
, or better a plain arr[i][j]
(which is the same thing). You missed the extra *
which made it print something that has absolutely nothing to do with the content of your array. Again, initialize your array in main
to something else to see that the results you are printing in C have absolutely nothing to do with the your intended content of the array.
If you change the printf
statement as shown above, your code will most likely crash because of the array-passing bug I described initially.
One more time: you cannot pass a int[4][4]
array as an int **
pseudo-array. This is what the C++ is telling you in the error message. And, I'm sure, this is what your C compiler told you, but you probably ignored it, since it was "just a warning".
The problem is, that
int a[4][4];
will actually be stored in a physically continuous memory. So, to access an arbitrary part of your 4x4 array, the function "print" needs to know the dimensions of the array. For example the following little piece of code, will access the same part of the memory in two different ways.
#include <iostream>
void print(int a[][4]) {
for (int i = 0; i <4; i++) {
for (int j = 0; j < 4; j++) {
//accessing as 4x4 array
std::cout << a[i][j] <<std::endl;
//accessing corresponding to the physical layout in memory
std::cout << *(*(a)+ i*4 + j) << std::endl;
}
}
}
int main() {
int a[4][4];
//populating the array with the corresponding indices from 0 to 15
int m = 0;
for (int i = 0; i<4; i++) {
for (int j= 0; j < 4; j++) {
a[i][j] = m;
m++;
}
}
print(a);
}
So the memory layout doesn't change but the way of accessing does. It can be visualized like a checkerboard.
0 1 2 3
----------
0| 1 2 3 4
1| 5 6 7 8
2| 9 10 11 12
3|13 14 15 16
But the real physical memory looks like this.
0*4+0 0*4+1 0*4+2 0*4+3 1*4+0 1*4+1 1*4+2 1*4+3 2*4+1 etc.
-----------------------------------------------------
1 2 3 4 5 6 7 8 9 etc.
In c++ the data of an array is stored row-by-row and the length of a row (in this case 4) is always necessary to get to the proper memory offset for the next row. The first subscript therefore only indicates the amount of storage that is needed when the array is declared, but is no longer necessary to calculate the offset afterwards.
#include<stdio.h>
void print(int arr[][4], int s1, int s2) {
int i, j;
printf("\n");
for(i = 0; i<s1; i++) {
for(j = 0; j<s2; j++) {
printf("%d, ", *((arr+i)+j));
}
}
printf("\n");
}
int main() {
int a[4][4] = {{0}};
print(a,4,4);
}
This will work, where by work I mean compile. @AndreyT explained why your version doesn't work already.
This is how you should pass a 2d array.
For clarity, you can also specify both sizes in the function declaration:
#include<stdio.h>
void print(int arr[4][4], int s1, int s2) {
int i, j;
printf("\n");
for(i = 0; i<s1; i++) {
for(j = 0; j<s2; j++) {
printf("%d, ", *((arr+i)+j));
}
}
printf("\n");
}
int main() {
int a[4][4] = {{0}};
print(a,4,4);
}
Both will work.
You should also change *((arr+i)+j)
to either a[i][j]
(preferably) or *(*(arr+i)+j)
if your intention is to access the j
th element of row i
.