Параметр функции print
имеет тип int *
.
print(int *p)
Таким образом, разыменовав указатель в выражении (*p)[i]
, вы получите скалярный объект типа int
. Вы не можете применять оператор индексации к скалярным объектам типа int
.
С другой стороны, в этом вызове
print(arr);
аргумент, имеющий тип int[3][3]
, имеет видпреобразован в указатель на свой первый элемент. Элементы массива имеют тип int[3]
. Таким образом, тип выражения после неявного преобразования массива в указатель на его первый элемент: int ( * )[3]
.
И сообщение об ошибке указывает на эту проблему
Main.cpp:16:4: error: no matching function for call to 'print'
print(arr);
^~~~~
, поскольку компиляторне может найти функцию с именем print, которая принимает аргумент типа int ( * )[3]
.
Таким образом, параметр функции print
должен быть объявлен как
print( int p[][3] )
или
print( int ( *p )[3] )
И так как массив не изменяется в функции, он должен быть объявлен с квалификатором const
.
Определение функции в этом случае будет выглядеть (если вы хотитеиспользуйте указатели)
void print( const int p[][3] )
{
for( const int ( *row )[3] = p; row != p + 3; ++row )
{
for ( const int *col = *row; col != *row + 3; ++col )
{
std::cout << *col << ' ';
}
std::cout << '\n';
}
}
Вот демонстрационная программа.
#include <iostream>
void print( const int p[][3] )
{
for( const int ( *row )[3] = p; row != p + 3; ++row )
{
for ( const int *col = *row; col != *row + 3; ++col )
{
std::cout << *col << ' ';
}
std::cout << '\n';
}
}
int main()
{
const size_t N = 3;
int arr[N][N] =
{
{ 1, 2, 3 } ,
{ 4, 5, 6 } ,
{ 7, 8, 9 }
};
print( arr );
return 0;
}
Его вывод
1 2 3
4 5 6
7 8 9
Однако этот подход имеет серьезный недостаток. Функция использует магическое число 3
.
Лучше переписать функцию по крайней мере, как
#include <iostream>
const size_t N = 3;
void print( const int p[][N], size_t rows )
{
for( const int ( *row )[N] = p; row != p + rows; ++row )
{
for ( const int *col = *row; col != *row + N; ++col )
{
std::cout << *col << ' ';
}
std::cout << '\n';
}
}
int main()
{
int arr[][N] =
{
{ 1, 2, 3 } ,
{ 4, 5, 6 } ,
{ 7, 8, 9 }
};
print( arr, sizeof( arr ) / sizeof( *arr ) );
return 0;
}
Также вы можете добавить еще один параметр с аргументом по умолчанию. Например,
std::ostream & print( const int p[][N], size_t rows, std::ostream &os = std::cout )
{
for( const int ( *row )[N] = p; row != p + rows; ++row )
{
for ( const int *col = *row; col != *row + N; ++col )
{
os << *col << ' ';
}
os << '\n';
}
return os;
}
Например,
#include <iostream>
const size_t N = 3;
std::ostream & print( const int p[][N], size_t rows, std::ostream &os = std::cout )
{
for( const int ( *row )[N] = p; row != p + rows; ++row )
{
for ( const int *col = *row; col != *row + N; ++col )
{
os << *col << ' ';
}
os << '\n';
}
return os;
}
int main()
{
int arr[][N] =
{
{ 1, 2, 3 } ,
{ 4, 5, 6 } ,
{ 7, 8, 9 }
};
print( arr, sizeof( arr ) / sizeof( *arr ) ) << '\n';
return 0;
}
И наконец вы можете написать шаблонную функцию.
#include <iostream>
template <typename T, size_t N>
std::ostream & print( const T ( &p )[N][N], std::ostream &os = std::cout )
{
for( const int ( *row )[N] = p; row != p + N; ++row )
{
for ( const int *col = *row; col != *row + N; ++col )
{
os << *col << ' ';
}
os << '\n';
}
return os;
}
int main()
{
const size_t N = 3;
int arr[][N] =
{
{ 1, 2, 3 } ,
{ 4, 5, 6 } ,
{ 7, 8, 9 }
};
print( arr ) << '\n';
return 0;
}