The array defined in this declaration
const char* a[][3] = {{"abc", "1"}, {"def", "2"}, {"ghi", "3"}};
has type const char *[3][3]
.
Take into account that the array has three "columns" there is explicitly specified 3 columns in the array declaration.
const char* a[][3] =....
^^^
Elements in the last column are initialized by NULL
.
When an array is used in expressions as for example as an argument it is explicitly converted to pointer to its first element.
That is if you use the above shown array as an argument then it is converted to type
const char * ( * )[3]
It is not the same type as char ***
So the function should ve declared like
void print( const char * ( *products )[3], size_t rows );
or like
void print( const char * products[][3], size_t rows );
and the function should be called like
print( a, 3 );
You may specify one more parameter that sets the number of columns you want for example to output
void print( const char * ( *products )[3], size_t rows, size_t cols );
In this case the function can be called like
print( a, 3, 2 );
However the array itself in any case has 3 columns.:)
Or if the compiler supports variable length arrays like
void print( size_t rows, size_t cols, const char * ( *products )[cols] );
or for readability
void print( size_t rows, size_t cols, const char * products[rows][cols] );
and it can be called like
print( 3, 3, a );
Here is a demonstrative program that shows two ways of the function declaration
#include <stdio.h>
#include <string.h>
#define N 3
void print1( const char *product[][N], size_t rows )
{
for ( size_t i = 0; i < rows; i++ )
{
for ( const char **p = product[i]; *p; ++p )
{
printf( "%s ", *p );
}
printf( "\n" );
}
}
void print2( size_t rows, size_t cols, const char *product[rows][cols] )
{
for ( size_t i = 0; i < rows; i++ )
{
for ( const char **p = product[i]; *p; ++p )
{
printf( "%s ", *p );
}
printf( "\n" );
}
}
int main( void )
{
const char * a[][N] =
{
{ "abc", "1" },
{ "def", "2" },
{ "ghi", "3" }
};
print1( a, N );
printf( "\n" );
size_t n = N;
const char * b[n][n];
memcpy( b, a, sizeof( a ) );
print2( n, n, b );
printf( "\n" );
}
Its output is
abc 1
def 2
ghi 3
abc 1
def 2
ghi 3
Take into account that variable length arrays if they are supported by the compiler may not be initialized then they are defined.