C中的“”(星号修饰符)是什么意思?
在试图实现一个C11parsing器(为了教育目的)时,我发现在C11(470页),但也在C99(412页) (感谢Johannes!), 直接声明符被定义为:
(6.7.6) direct-declarator: direct-declarator [ type-qualifier-list? * ]
起初,我认为这是语法错误(types列表不应该是可选的)。 但是,当我在我的参考编译器(铿锵声)中尝试了这一点,我得到了一个意想不到的错误:
int array[*] = { 1, 2, 3 }; // error: star modifier used outside of function prototype
很明显,(在叮当中)这叫做星形修饰符 。
我很快就了解到,他们只能用于function签名:
void foobar(int array[*])
但是,他们只能用在声明中。 试图在函数定义中使用它也会导致错误:
void foobar(int array[*]) { // variable length array must be bound in function definition }
所以据我所知,预期的行为是在函数声明中使用[*]
,然后在函数定义中使用一个固定的数字。
// public header void foobar(int array[*]); // private implementation void foobar(int array[5]) { }
但是,我从来没有见过,也不太明白它的目的。
- 它的目的是什么,为什么添加?
- 与
int[]
什么区别? -
int *
什么区别?
它的目的是什么,为什么添加?
当可变长度的二维数组用作函数参数时,可以看到目的。 function
int foo(int n, int m, int a[n][m]) {...}
可以作为以下任何一个原型
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]);
在二维数组的情况下,当用作函数参数时,二维的大小不能省略。 如果省略函数原型中第一个variables的名称,那么就不可能指定数组的长度(第二维)。 *
给出的线索,arrays的长度将由第二个参数确定。
与
int[]
什么区别?
int *
什么区别?
在1D数组的情况下,用于函数定义
int bar(int n, int a[n]} {...}
以下任何一个原型都是有效的
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]);
在这种情况下,既不需要*
n
也不需要编译器将int [*]
和int [n]
视为int *
。 所以,对于一维数组,你看不到太多的区别。
注意:使用可变长度数组作为函数参数时,参数的顺序很重要。 bar
前四个原型的参数顺序可以切换,但后两个参数不能是数组本身。
int bar (int a[n], int n); //Wrong. Compiler has not yet seen 'n'.
C99的C原理文件说
一个函数原型可以使用一个特殊的语法来使用具有可变长度数组types的参数(§6.7.5.2)
int minimum(int, int [*][*]);
这与其他C原型是一致的,其中参数的名称不需要指定。
与int []有什么区别
与int *有什么不同?
我认为这仅仅是函数原型中的那些types意味着“指针”,而非顶级位置中的int[*]
( 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("%d\n", a[1][0]); }
至于目的,当索引函数定义中的数组时,编译器需要知道在给出第一个索引( x[i]
跳过上面f
i * n
整数x[i]
时下一个索引要跳过多less个整数。 但是这个信息在非定义的原型声明中是不需要的,因此它可以被忽略并且被*
代替。