What does “[*]” (star modifier) mean in C? [duplicate]
What does “[*]” (star modifier) mean in C? [duplicate]
This question already has an answer here:
While trying to implement a C11 parser (for educational purposes), I found that in C11 (p. 470) but also in C99 (p. 412) (thanks Johannes!), the direct declarator is defined as:
(6.7.6) direct-declarator:
direct-declarator [ type-qualifier-list? * ]
At first, I thought this was an error in the grammar (the type list shouldn't be optional). However, when I tried this out in my reference compiler (clang), I got an rather unexpected error:
int array[*] = { 1, 2, 3 };
// error: star modifier used outside of function prototype
So apparently, (in clang) this is called the star modifier.
I quickly learned that they can only be used in function signatures:
void foobar(int array[*])
However, they can only be used in the declaration. Trying to use it in a function definition results in an error as well:
void foobar(int array[*]) {
// variable length array must be bound in function definition
}
So as far as I can tell, the intended behaviour is to use [*]
in the function declaration and then use a fixed number in the function definition.
[*]
// public header
void foobar(int array[*]);
// private implementation
void foobar(int array[5]) {
}
However, I have never seen it and I don't quite understand the purpose of it either.
int
int *
This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.
int
int[*]
You're right, I forgot to mention it but I searched for the errors that I got from clang and they corresponded to their VLA unit test suite. Still, I would like to know their purpose. Thanks!
– elslooo
Aug 4 '16 at 19:04
22 views and this is already the first google result for "c star modifier". You've hit upon an obscure feature.
– ApproachingDarknessFish
Aug 4 '16 at 19:10
Since when is Clang "the reference compiler"?
– user2357112
Aug 4 '16 at 19:11
@user2357112 I don't think he meant it in any specific capacity, just that it was the compiler that he personally is using to check that his interpretation of the standard is sane.
– Random832
Aug 5 '16 at 5:23
2 Answers
2
What is its purpose, why was it added?
Purpose is seen when a variable length two dimentional array is used as a function parameter. The function
int foo(int n, int m, int a[n][m]) {...}
can be prototyped as any of the following
int foo(int , int, int [*]);
int foo(int , int, int a[*][*]);
int foo(int , int, int (*a)[*]);
int foo(int n, int, int a[n][*]);
int foo(int , int m, int a[*][m]);
int foo(int , int m, int (*a)[m]);
int foo(int n, int m, int a[n][m]);
In case of two dimensional array, when used as function parameter, size of the second dimension can't be omitted. If the name of first variables in function prototype is omitted then it wouldn't be possible to specify the length (second dimension) of the array. The *
gives the clue that the length of the array will be determined by the second parameter.
*
What's the difference with int
?
What's the difference with int *
?
int
int *
In case of 1D array, for the function definition
int bar(int n, int a[n]} {...}
any of the following prototype is valid
int bar (int , int *);
int bar (int , int [*]);
Int bar (int , int );
int bar (int n, int a);
int bar (int n, int a[n]);
int bar (int n, int [n]);
In this case neither *
nor n
is necessary as compiler will treat both of int [*]
and int [n]
as int *
. So, with one dimensional array you can't see much difference.
*
n
int [*]
int [n]
int *
NOTE: When using variable length array as a function parameter, order of parameter is important. Order of parameters for first four prototypes of bar
can be switched, but in latter two first parameter must not be the array itself.
bar
int bar (int a[n], int n); //Wrong. Compiler has not yet seen 'n'.
This directly answers the question instead of just quoting a standard.
– alvits
Aug 4 '16 at 19:15
The standard quote directly answers the question, and it's authoritative, because it's from the standard. There's nothing wrong with standard quotes. (Come to think of it, that quote's from the rationale document, not the standard, though.)
– user2357112
Aug 4 '16 at 19:18
@user2357112 there was another answer not by me who directly quoted the Standard. I guess alvits refes to that. Mine doesn't quote the C standard, as you correctly point out
– Johannes Schaub - litb
Aug 4 '16 at 19:22
int bar (int [*], int);
is correct.– M.M
Aug 5 '16 at 4:30
int bar (int [*], int);
It's not that there's anything wrong with quoting the standard, per se. In fact, it's usually a good idea. The problem comes when the answer consists solely of a quotation from the standard without any sort of explanation. Generally, if someone was able to read and understand exactly what was meant by the standard, they wouldn't be asking a question about it on Stack Overflow. So a good answer (to a question where it is relevant) really needs to do both. If you had to choose one or the other, I'd have to agree with alvits and say that an explanation is superior to a quotation.
– Cody Gray♦
Aug 5 '16 at 4:38
The C rationale document for C99 says
A function prototype can have parameters that have variable length array types (§6.7.5.2) using a special syntax as in
int minimum(int, int [*][*]);
This is consistent with other C prototypes where the name of the parameter need not be specified.
What's the difference with int
What's the difference with int *.
I think it's simply that those types in a function prototype means "pointer", while a [*]
in a non-top position (int[*]
still equals int
I think, in a function prototype) actually is valid and means array
[*]
int[*]
int
// not recommended though: it is now unclear what the parameters
// mean to human callers!
void f(int, int [*]);
void f(int n, int x[n]) {
x[1][0] = 1;
}
int main() {
int a[2][1];
f(1, a);
printf("%dn", a[1][0]);
}
As for the purpose, when indexing the array in the function definition, the compiler needs to know how many integers of the next index to skip when giving the first index (x[i]
skips i * n
integers in f
above). But this information is not needed in the non-defining prototype declaration, hence it can be left out and replaced by *
.
x[i]
i * n
f
*
Your function prototype should be
void f(int, int x[*])
. When you give the first parameter a name, then there's no need for the *
. The whole point of this feature is that you can use old fashioned function prototypes that don't name the parameters.– user3386109
Aug 4 '16 at 19:33
void f(int, int x[*])
*
@user3386109 hmm, was naming the parameters not allowed in C89? I thought this was always allowed? Why woud leaving out names be "old fashioned"? But, true, the motivation is less high if you name the parameter anyway
– Johannes Schaub - litb
Aug 5 '16 at 6:55
It's been in C since C99. I believe it means "placeholder for VLA number here".
int
is not valid, butint[*]
is (in a non-defining function prototype).– Johannes Schaub - litb
Aug 4 '16 at 19:03