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.
Help me to understand 2D arrays in C
How to create a 2 dimensional array in c?
Passing variable size 2d-Array to C external library
Why does this work? Pointers and 2D arrays
It's about memory layout. An array is a collection of objects in the contiguous memory location. If an array consists of subarrays (like a[2][3]), it means those subarrays are also contiguous, and you can pass from the end of the row 0 to the beginning of the row 1 seamlessly:
int a[2][3];
int *b = &a[0][2]; //pointer to the end of row 0
if(b+1 == &a[1][0])
printf("Yes!\n"); More on reddit.com How to initialize a 2D array in C?
How to take input in a 2D array in C?
What is the difference between 1D and 2D arrays in C?
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.
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 }
~
So I've come to the conslusion that int (*arr)[M] and int *arr[M] aren't the same. int arr[M] is the array whose elements type are pointer to int. ( I think it works this way: Compiler first sees [M] and know that the array will have M elements, then sees the name ''arr'' wich later is linked to values of the array and at the end it sees the type wich is " int ".) I dont understand how it works with (*arr)[M]. Is it the same as the *arr[M] but arr is actually a pointer that points to array of ints with M elements. Please correct me if Im wrong.
I want to create a 2 dimensional array in C that will be filled with values from a text file. These values are integers and contain 5 rows by 10 columns. Each integer is separated by a space and each column by an end of line. I am using int[ , ] xxx = new int[5,10]; I am getting 9 errors. Ranging from C2143,C3409,C2059. What am I doing wrong?