Этот
int **arr = (int **)malloc(sizeof(int *) * 3);
не является объявлением или выделением двумерного массива
Здесь создается одномерный массив с типом элемента int *
. И затем каждый элемент одномерного массива в свою очередь указывает на выделенный одномерный массив с типом элемента int
.
Это объявление двумерного массива
const int row = 3;
const int col = 4;
int arr[row][col] = {
{1,2,3,4},
{3,4,5,6},
{5,6,7,8}
};
это неверно. Массивы переменной длины (и вы объявили массив переменной длины) не могут быть инициализированы в объявлении.
Вместо этого вы можете написать
enum { row = 3, col = 4 };
int arr[row][col] = {
{1,2,3,4},
{3,4,5,6},
{5,6,7,8}
};
Когда такой массив передается функции, он неявно преобразован в указатель на свой первый элемент типа int ( * )[col]
.
Вы можете передать его функции, у которой есть параметр типа массива переменной длины, следующим образом
void my_func( size_t row, size_t col, int arr[row][col] )
{
printf("test2: %d", arr[0][1]);
}
Или, если поместить определение перечисления перед объявлением функции
enum { row = 3, col = 4 };
, то функция также может быть объявлена как
void my_func( int arr[][col], size_t row )
{
printf("test2: %d", arr[0][1]);
}
Вот демонстрационная программа, которая показывает три различных подхода , Первый, когда массив определяется с константами времени компиляции для размеров массива. Второй, когда создается массив переменной длины. И третий, когда одномерный массив указателей на одномерные массивы выделяется динамически.
#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 );
}
Вывод программы:
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
Обратите внимание, что функция output2
можно использовать с массивом arr1
так же, как и с массивом arr2
.