Given any type T
, T arr[N];
declares a variable arr
of type T[N]
, which is an array and not a pointer. When you use arr
in almost all contexts, array to pointer conversions happen, giving the incorrect illusion that arr
is a pointer of type T*
.
char s[n][16] = { "Hello", "Bye", "Sky" };
declares s
as an array of n
elements of type char[16]
. Now, when array to pointer conversion happens, s
decays into a pointer of type char (*)[16]
. Hence, your function needs to have the signature
void print(char (*s)[16], int n);
Which is equivalent to
void print(char s[][16], int n);
the []
is interpreted as a pointer by the compiler.
To make these complex types more readable, a type alias may be used.
using T = char[16];
void print(T s[], int n);
Addressing some concerns
As pointed out in the comments, std::string
should almost always be preferred over a char
array. If you have performance concerns, benchmark before doing this. I really doubt much performance gains can be observed in most cases.
Declaring an array with length n
which is an int
is not standard C++. It is an extension provided by your compiler, it is not portable and in most cases not necessary.
int n = 3;
char vla[n]; // this is a variable length array
char arr[3]; // this is just an array
char* darr = new char[3]; // this is a pointer pointing to dynamically allocated memory
std::string str; // but instead, this is just better