I think that it is because the former is an array of pointers to char and the latter is a pointer to an array of chars, and we need to properly specify the size of the object being pointed to for our function definition. In the former;
function(char * p_array[])
the size of the object being pointed to is already included (its a pointer to char), but the latter
function(char (*p_array)[])
needs the size of the array p_array points to as part of p_array’s definition?
I’m at the stage where I’ve been thinking about this for too long and have just confused myself, someone please let me know if my reasoning is correct.
Both are valid in C but not C++. You would ordinarily be correct:
However, the arrays decay to pointers if they appear as function parameters. So they become:
In an array type in C, one of the sizes is permitted to be unspecified. This must be the leftmost one (whoops, I said rightmost at first). So,
(You can chain them… but we seldom have reason to do so…)
There is a catch, and the catch is that an array type with
[]in it is an incomplete type. You can pass around a pointer to an incomplete type but certain operations will not work, as they need a complete type. For example, this will not work:This is an error because in order to find the address of
x[2], the compiler needs to know how bigx[0]andx[1]are. Butx[0]andx[1]have typeint []— an incomplete type with no information about how big it is. This becomes clearer if you imagine what the “un-decayed” version of the type would be, which isint x[][]— obviously invalid C. If you want to pass a two-dimensional array around in C, you have a few options:Pass a one-dimensional array with a size parameter.
Use an array of pointers to rows. This is somewhat clunky if you have genuine 2D data.
Use a fixed size.
Use a variable length array (C99 only, so it probably doesn’t work with Microsoft compilers).
This is a frequent problem area even for C veterans. Many languages lack intrinsic “out-of-the-box” support for real, variable size, multidimensional arrays (C++, Java, Python) although a few languages do have it (Common Lisp, Haskell, Fortran). You’ll see a lot of code that uses arrays of arrays or that calculates array offsets manually.