hgiesel
hgiesel

Reputation: 5648

Using char* a[] vs char a[][]

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

Answers (2)

haccks
haccks

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

Lundin
Lundin

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

Related Questions