Reputation: 5648
I know that when used as function parameter char* a[]
is equivalent to char a[][]
.
When used as function parameter char* a[]
is equivalent to char** a
. Also known as Array to pointer conversion to some.
However when used in block scope they are not the same, and I'm confused as when I should prefer one over the other, or if I should skip char a[][]
, as I usually tend to see char* a[]
in other people's code.
One argument against char a[][]
is obviously that you have to give a fixed size for the C-strings it will contain, but does that affect performance in any way?
Should I prefer this:
char* a[] = {"hello", "world"};
Or this:
char a[][10] = {"hello", "world"};
Upvotes: 2
Views: 2569
Reputation: 105992
Adjustment of array type to pointer type works only when it is declared as a parameter of a function.
As a function parameter char* a[]
will be adjusted to char** a
and char a[][10]
to char (*a)[10]
. Otherwise char* a[]
declares a
as an array of pointers to char
while char a[][10]
declares a
an array of arrays of char
.
Preference of
char* a[] = {"hello", "world"};
over this
char a[][10] = {"hello", "world"};
make sense when you want to save some bytes of memory. In latter case for each of a[0]
and a[1]
10 bytes are allocated. Note that in case of char* a[]
, strings pointed by the elements of a
are immutable.
If you want contiguous memory allocation then go with char a[][10]
.
Upvotes: 2
Reputation: 213266
The key to understanding the seemingly strange syntax cases of function parameters is to understand array decay. This is all about one rule in C that says, whenever you pass an array as parameter to a function, it decays into a pointer to the first element of that array (*).
So when you write something like
void func (int a[5]);
then at compile-time, the array gets replaced with a pointer to the first element, making the above equal to:
void func (int* a);
This rule of pointer decay applies recursively to multi-dimensional arrays. So if you pass a multi-dimensional array to a function:
void func (int a[5][3]);
it still decays to a pointer to the first element. Now as it happens, a 2D array is actually an array of arrays. The first element is therefore a one-dimensional array, with size 3 in this example. You get an array pointer to that array, the type int(*)[3]
. Making the above equivalent to
void func (int (*a)[3]);
And this is actually the reason why we can omit the left-most dimension of the array parameter, and only that dimension. Upon doing so we make an array of incomplete type, which you normally wouldn't be able to use: for example you can't write code like int array[];
inside a function's body. But in the parameter case, it doesn't matter that the left-most dimension isn't specified, because that dimension will "decay away" anyway.
(*) Source, C11 6.7.6.3/7:
A declaration of a parameter as ‘‘array of type’’ shall be adjusted to ‘‘qualified pointer to type’’, ...
Upvotes: 8