Reputation: 43
I want to make a 2 dimensional array in C.
I know 1 way to make it like this.
#include <stdlib.h>
void my_func(int **arr)
{
printf("test2: %d\n", arr[0][1]);
}
int main(void)
{
const int row = 3;
const int col = 4;
int **arr = (int **)malloc(sizeof(int *) * 3);
arr[0] = (int *)malloc(sizeof(int) * 4);
arr[1] = (int *)malloc(sizeof(int) * 4);
arr[2] = (int *)malloc(sizeof(int) * 4);
arr[0][0] = 1;
arr[0][1] = 2;
arr[0][2] = 3;
arr[0][3] = 4;
arr[1][0] = 3;
arr[1][1] = 4;
arr[1][2] = 5;
arr[1][3] = 6;
arr[2][0] = 5;
arr[2][1] = 6;
arr[2][2] = 7;
arr[2][3] = 8;
printf("test1: %d\n", arr[0][1]);
my_func(arr);
}
In this case, the array can be passed to the function well as an argument. But it's not that pretty. If the array has lots of values (e.g 20*20), I need to type every single value line by line.
So I searched it and found out a way to make an array like this.
#include <stdio.h>
void my_func(int **arr)
{
printf("test2: %d", arr[0][1]);
}
int main(void)
{
const int row = 3;
const int col = 4;
int arr[row][col] = {
{1,2,3,4},
{3,4,5,6},
{5,6,7,8}
};
printf("test1: %d", arr[0][1]);
my_func(arr);
}
It's concise and don't make me exhausted. But something is wrong when array is passed to a function. And when compiling, there is a warning as below
test_2D_array.c:20:11: warning: incompatible pointer types passing 'int [3][4]' to
parameter of type 'int **' [-Wincompatible-pointer-types]
my_func(arr);
^~~
test_2D_array.c:3:20: note: passing argument to parameter 'arr' here
void my_func(int **arr)
^
1 warning generated.
and Even the function can't access the array argument. There is a segmentation fault.
So I want to know the best way to make array which can be passed toany function as an argument and less exhausting than my first code.
Thank you for reading.
Upvotes: 4
Views: 5939
Reputation: 1153
First you cannot initialize a 2D array with variable size, as 'Vlad from Moscow' mentioned in his answer.
Instead, you just need to specify the size of your 2nd dimension, leaving the 1st dimension blank.
Second your my_func(int **arr)
is expecting pointer to pointer to int
and you are just passing the address of an array, that's why compiler is throwing an error of incompatibility.
Your fixed code will look like this:
#include <stdio.h>
void my_func(int **arr)
{
printf("test2: %d", arr[0][1]);
}
int main(void)
{
int arr[][4] = {1,2,3,4,
3,4,5,6,
5,6,7,8};
int *p = (int *)arr;
int **p1 = &p;
printf("test1: %d", arr[0][1]);
my_func(p1);
}
Now there's no use of const int row = 3
& const int column = 4
so you can remove them.
Upvotes: 1
Reputation: 573
Suppose there is no dynamic allocation.
1 #include <stdio.h>
1
2 void func(int *arr, int row, int col) {
3 int i, j;
4
5 for (i = 0; i < row * col; i++) {
6 if (i && (i % col == 0))
7 printf("\n");
8 printf("%d ", arr[i]);
9 }
10
11 printf("\n");
12 }
13
14 int main(int argc, char *argv[]) {
15 // can be this
16 int arr1[] = {
17 1,2,3, // row 0
18 4,5,6 // row 1
19 };
20
21 // or this way
22 int arr2[2][3] = {
23 {0,1,2}, // row 0
24 {4,5,6} // row 1
25 };
26
27 func(arr1, 2, 3);
28 func((int*)arr2, 2, 3);
29 return 0;
30 }
~
Upvotes: 2
Reputation: 310980
This
int **arr = (int **)malloc(sizeof(int *) * 3);
is not a declaration or allocation of a two-dimensional array
Here a one-dimensional array with the element type int *
is created. And then each element of the one-dimensional array in turn points to an allocated one dimensional array with the element type int
.
This declaration of a two-dimensional array
const int row = 3;
const int col = 4;
int arr[row][col] = {
{1,2,3,4},
{3,4,5,6},
{5,6,7,8}
};
is incorrect. Variable length arrays (and you declared a variable length array) may not be initialized in declaration.
You could write instead
enum { row = 3, col = 4 };
int arr[row][col] = {
{1,2,3,4},
{3,4,5,6},
{5,6,7,8}
};
When such an array is passed to a function it is implicitly converted to pointer to its first element of the type int ( * )[col]
.
You could pass it to a function that has a parameter of the type of a variable length array the following way
void my_func( size_t row, size_t col, int arr[row][col] )
{
printf("test2: %d", arr[0][1]);
}
Or if to place the definition of the enumeration before the function declaration
enum { row = 3, col = 4 };
then the function could be also declared like
void my_func( int arr[][col], size_t row )
{
printf("test2: %d", arr[0][1]);
}
Here is a demonstrative program that shows three different approaches. The first one when an array is defined with compile-time constants for array sizes. The second one when a variable length array is created. And the third one when a one-dimensional array of pointer to one-dimensional arrays are allocated dynamically.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
enum { row = 3, col = 4 };
void output1( int a[][col], size_t row )
{
for ( size_t i = 0; i < row; i++ )
{
for ( size_t j = 0; j < col; j++ )
{
printf( "%d ", a[i][j] );
}
putchar( '\n' );
}
}
void output2( size_t row, size_t col, int a[row][col] )
{
for ( size_t i = 0; i < row; i++ )
{
for ( size_t j = 0; j < col; j++ )
{
printf( "%d ", a[i][j] );
}
putchar( '\n' );
}
}
void output3( int **a, size_t row, size_t col )
{
for ( size_t i = 0; i < row; i++ )
{
for ( size_t j = 0; j < col; j++ )
{
printf( "%d ", a[i][j] );
}
putchar( '\n' );
}
}
int main(void)
{
int arr1[row][col] =
{
{1,2,3,4},
{3,4,5,6},
{5,6,7,8}
};
output1( arr1, row );
putchar( '\n' );
const size_t row = 3, col = 4;
int arr2[row][col];
memcpy( arr2, arr1, row * col * sizeof( int ) );
output2( row, col, arr2 );
putchar( '\n' );
int **arr3 = malloc( row * sizeof( int * ) );
for ( size_t i = 0; i < row; i++ )
{
arr3[i] = malloc( col * sizeof( int ) );
memcpy( arr3[i], arr1[i], col * sizeof( int ) );
}
output3( arr3, row, col );
putchar( '\n' );
for ( size_t i = 0; i < row; i++ )
{
free( arr3[i] );
}
free( arr3 );
}
The program output is
1 2 3 4
3 4 5 6
5 6 7 8
1 2 3 4
3 4 5 6
5 6 7 8
1 2 3 4
3 4 5 6
5 6 7 8
Pay attention to that the function output2
can be used with the array arr1
the same way as it is used with the array arr2
.
Upvotes: 5
Reputation: 64682
It needs a funny looking typecast, but I did it this way:
#include <stdio.h>
void my_func(int **arr, int cols)
{
int (*matrix)[cols] = arr;
printf("test2: %d\n", matrix[0][1]);
}
int main(void)
{
const int row = 3;
const int col = 4;
int arr[3][4] = {
{1,2,3,4},
{3,4,5,6},
{5,6,7,8}
};
printf("test1: %d\n", arr[0][1]);
my_func(arr, col);
}
Upvotes: -2
Reputation: 11047
The function can be declared as
void my_func(int arr[][4])
{
printf("test2: %d", arr[0][1]);
}
Note that you don't have to specify the size of the first dimension.
Upvotes: 1