38

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 []?

13
  • Did you checked int sum(int n, int a[]); Commented Jun 28, 2013 at 18:53
  • 2
    y@aaronman; yes. its c99 feature. Commented Jun 28, 2013 at 18:54
  • 2
    So... int a[*] is an array of pointers or a variable-length array? It's not simple to understand just seeing code...? I mean... is "int a[*]" the same as "int *a[]" or just "int a[]"? Commented Jun 28, 2013 at 18:54
  • 4
    Related/Duplicate question. See answer by Jens Gustedt. Commented Jun 28, 2013 at 19:03
  • 3
    @haccks If you read the end of his answer, he essentially explains what AndreyT explains below, which is that [*] is useful if you don't name your preceeding length parameters in your function prototypes. Commented Jun 28, 2013 at 19:11

2 Answers 2

62

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".

Sign up to request clarification or add additional context in comments.

5 Comments

Sometimes you cannot easily name the parameters in prototypes. When writing a library header, you want to avoid names that might collide with names the users of your library are using in preprocessor macros. So you must omit names or step into the reserved name space (in cooperation with the implementation) or have the library reserve part of the name space (as with a prefix such as “MyLibrary_”). The latter two can get ugly.
@AndreyT; Please elobrate your statement The [*] becomes important in situations when the "variable arrayness" of the type is not lost, as would be the case with 2D VLA. in your answer.
@EricPostpischil; It bounds over head :(
@haccks: I'm referring to the fact that the first [] in array parameter declaration in always lost. The parameter decays to a pointer. That applies to all array parameter declarations, regardless of whether they are VLA or not. (I stated this in the answer). The only way to "inject" permanent non-disappearing arrayness" into a type in C is to make it a pointer to an array, like int (*p)[5] or int (*p)[n]. In parameter declarations this is equivalent to 2D array declaration.
@haccks In the case of a variable array, like int arr[n][m], the compiler needs to know the size m because in the case of an array access like arr[2][3], it has to internally convert it to something like *(arr + 2 * m + 3) (Notice the m in the expression). In ANSI C, your only option would be to pass int *arr and do the *(arr + 1 * m + 1) part manually, but in C99, you can have the compiler handle it for you, therefore the new syntax. The first size (in this case n) is never needed, since it's element are always right next to each-other (sizeof int bytes in this case).
4

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.

5 Comments

@AlejandroIván Nah, that's a different syntax.
Weird... seems like C99 allows variable-length arrays declared this way.
@AlejandroIván look at new post
@H2CO3; Which syntax is this? Its too confusing man. If you know please give an answer.
@haccks Array of ints: int arr[N]; array of pointers-to-int: int *arr[N]; - pointer-to-array-of-ints: int (*ptr)[N], variable length array: int arr[<non-const expression>]; - VLA in function argument list: the same or int arg[*];

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.