Reputation: 285
why this error(picture 1) happened when I want to input a 2d array to a function?
#include <stdio.h>
#include <stdlib.h>
void pr(int** a){
printf("%d", a[0][0]);
}
int main(){
int a[5][5]={{1,4,7,11,15},{2,5,8,12,19},{3,6,9,16,22},{10,13,14,17,24},{18,21,23,26,30}};
pr(a);
}
Upvotes: 3
Views: 13319
Reputation: 4547
Arrays and pointers can not be used interchangeably in all possible use cases, and you just happened to stumble into one of them. At times, an int
array can be implicitly converted into a pointer, and at times it, well, shouldn't be.
In your case, implicitly (or explicitly) converting a
to an (int **
) would not work, simply because a
points to the first element in your 2d array when considered as a pointer. Converting a
to an int **
would make pr
lose the information on a
being an array. Consequently, handling it as a typical (int **
) in pr
and trying to dereference it twice would cause the first element in a
(a[0][0] = 1
) to be handled as an address and the value in that address would be looked up, which I believe is not the desired behavior of pr()
.
Ideally, you should declare pr
in a way that takes a 2D array as a parameter, not an int **
. A declaration of pr
with the mentioned fix is given below.
void pr(int a[][5]){
printf("%d", a[0][0]);
}
Now, you mention in the comments to your question that the definition of pr
can not be modified. In order not to modify pr()
, you would have to change the data structure you have in main
to something similar to the one given below.
int main(){
int a0[5]={1,4,7,11,15};
int a1[5]={2,5,8,12,19};
int a2[5]={3,6,9,16,22};
int a3[5]={10,13,14,17,24};
int a4[5]={18,21,23,26,30};
int *a[5] = {a0, a1, a2, a3, a4};
pr(a);
}
Note that the sample above is not the most syntactically concise way to achieve your goal. Also, check here to see this usage at work.
Upvotes: 5
Reputation: 753970
The core problem is that arrays and pointers are not the same (albeit they are closely related), and a 2D array is not an array of pointers.
This code shows three ways to fix up the problem. The array a0
is your array renamed and reformatted; the array a
is an array of pointers, and each pointer is a pointer to an array of 5 int
via a 'compound literal', a feature added to C99. I've upgraded the printing function to print all 25 elements of the array that is passed to it — and created two new printing functions with different interfaces that also print the entire array passed to them. I assume the array is square; a rectangular (non-square) matrix can be readily handled, especially by a variant on pr1()
such as pr2(int n, int m, int a[n][m])
— which is almost identical to pr1()
but needs a single adjustment internally to test j
against m
instead of n
.
#include <stdio.h>
static void pr0(int a[][5]);
static void pr1(int n, int a[n][n]);
static void pr(int **a)
{
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 5; j++)
printf("%3d", a[i][j]);
putchar('\n');
}
putchar('\n');
}
int main(void)
{
int a0[5][5] =
{
{ 1, 4, 7, 11, 15 },
{ 2, 5, 8, 12, 19 },
{ 3, 6, 9, 16, 22 },
{ 10, 13, 14, 17, 24 },
{ 18, 21, 23, 26, 30 },
};
int *a[] =
{
(int[]){ 1, 4, 7, 11, 15 },
(int[]){ 2, 5, 8, 12, 19 },
(int[]){ 3, 6, 9, 16, 22 },
(int[]){ 10, 13, 14, 17, 24 },
(int[]){ 18, 21, 23, 26, 30 },
};
pr(a);
pr0(a0);
pr1(5, a0);
return 0;
}
static void pr0(int a[][5])
{
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 5; j++)
printf("%3d", a[i][j]);
putchar('\n');
}
putchar('\n');
}
static void pr1(int n, int a[n][n])
{
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
printf("%3d", a[i][j]);
putchar('\n');
}
putchar('\n');
}
The sample output is wonderfully uniform:
1 4 7 11 15
2 5 8 12 19
3 6 9 16 22
10 13 14 17 24
18 21 23 26 30
1 4 7 11 15
2 5 8 12 19
3 6 9 16 22
10 13 14 17 24
18 21 23 26 30
1 4 7 11 15
2 5 8 12 19
3 6 9 16 22
10 13 14 17 24
18 21 23 26 30
The three blocks are the same. Given a choice, I'd use the technique in pr1()
, using VLAs (variable length arrays) in the interface. If you must stick with the int **
argument, you must stick with the array a
, or something quite similar. There are certainly other ways to create that. For example:
int *a[] = { a0[0], a0[1], a0[2], a0[3], a0[4] };
Upvotes: 7