Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why use an asterisk "[*]" instead of an integer for a VLA array parameter of a function?

When using variable-Length Array as parameter in function

int sum(int n, int a[n]); 

it is easy to understand first parameter(n) specifies the length of the second parameter(a). But encountered with another prototype used for VLAs as parameter

int sum(int n, int a[*]); 

is really difficult to understand why * is used instead of n inside []?

like image 352
haccks Avatar asked Jun 28 '13 18:06

haccks


2 Answers

The [*] syntax is intended to be used when declaring function prototypes. The key detail here is that in function prototypes you are not required to name your parameters, you just have to specify the type of each parameter.

In your example, if you leave the first parameter unnamed, then obviously you won't be able to use n in your second (array) parameter declaration. Yet, in many cases you have to tell the compiler that some parameter is a VLA. This is when the [*] syntax comes to the rescue.

In your case, if you omit the parameter names, the prototype might look as

int sum(int, int [*]); 

However, it is important to note that in your specific example this syntax is legal, but it is not exactly necessary. Just like with non-VLA arrays, an int [n] parameter is still equivalent to int * parameter (even for non-constant n). This means that you can simply prototype your function as

int sum(int, int []); 

or as

int sum(int, int *); 

and the prototype will still serve its purpose, i.e. it will properly match the function definition. In other words, VLA properties of a parameter declared as an 1D array are completely inconsequential and the [*] feature is not really needed with such VLA arrays.

The [*] becomes important in situations when the "variable arrayness" of the type is not lost, as would be the case with 2D VLA (or a pointer to a VLA). E.g. a function defined as

int sum2d(int n, int m, int a[n][m]) {   ... } 

might be prototyped as any of the following

int sum2d(int, int, int a[*][*]); int sum2d(int n, int, int a[n][*]); int sum2d(int, int m, int a[*][m]); int sum2d(int n, int m, int a[n][m]); 

All of the above prototypes properly match the function definition.

Of course, if you have the habit of always naming all parameters in function prototypes, then you'll never need this [*] syntax, since you will be able to use the last prototype in the above list.

P.S. Again, as is the case with all arrays in parameter declarations, the first [] is always inconsequential and always decays to a pointer, meaning that the following are also valid equivalent prototype declarations for the above sum2d

    int sum2d(int, int, int a[][*]);     int sum2d(int, int, int (*a)[*]);     int sum2d(int n, int m, int (*a)[m]); 

It is the second [] that really matters and has to be declared as "variable length".

like image 72
AnT Avatar answered Sep 30 '22 14:09

AnT


When you put the star in an actual function it gives this error test.c:3: error: ‘[*]’ not allowed in other than function prototype scope. After some research this is actually a way to declare a VLA in a function prototype, with the * in place of the variable name. VLA.
The issue at hand here is that if you put a variable instead of the star for a VLA, it will tell you that it is undeclared, so the star is a way that c99 built in to get around that.

like image 26
aaronman Avatar answered Sep 30 '22 14:09

aaronman