If the argument of printPerm is indeed a two-dimensional array then it can not be implicitly converted to type int **. If the argument has indeed type int ** then you need declare additional two parameters that will specify the number of subarrays and the number of elements in each subarray. Pointers in C++ do not encapsulate information about how many elements they refer to.
Let assume that argument was defined the following way
int m = 10;
int n = 20;
int **p = new int * [m];
for ( int i = 0; i < m; i++ ) p[i] = new int [n];
In this case the function should be defined as
void printPerm( const int **p, int m, int n )
{
for ( int i = 0; i < m; i++ )
{
for ( int j = 0; j < n; j++ )
{
std::cout << p[i][j];
}
std::cout << std::endl;
}
}
and called as
printPerm( p, m, n );
If the argument was defined the following way
const int M = 10;
const int N = 20;
int p[M][N];
then the function should be defined the following way
void printPerm( const int ( *p )[N], int m )
{
for ( int i = 0; i < m; i++ )
{
for ( int j = 0; j < N; j++ )
{
std::cout << p[i][j];
}
std::cout << std::endl;
}
}
and called as
printPerm( p, M );
Also for the second case there is a possibility to pass an array by reference. The function definition will look as
const int M = 10;
const int N = 20;
void printPerm( const int ( &p )[M][N] )
{
for ( int i = 0; i < M; i++ )
{
for ( int j = 0; j < N; j++ )
{
std::cout << p[i][j];
}
std::cout << std::endl;
}
}
And can be called as
int p[M][N];
printPerm( p );
EDIT: I have updated some typos.