来自
-link-的ANSI C语法给出了以下关于数组声明的规则:
(1) | direct_declarator '[' type_qualifier_list assignment_expression ']' (2) | direct_declarator '[' type_qualifier_list ']' (3) | direct_declarator '[' assignment_expression ']' (4) | direct_declarator '[' STATIC type_qualifier_list assignment_expression ']' (5) | direct_declarator '[' type_qualifier_list STATIC assignment_expression ']' (6) | direct_declarator '[' type_qualifier_list '*' ']' (7) | direct_declarator '[' '*' ']' (8) | direct_declarator '[' ']'
现在我有一些关于这些的问题:
>只能在C99中使用(1) – (6)(3)除外
>(4)和(5)是什么?关键字“静态”让我感到困惑
>哪里使用(6)?
>以下两个功能原型有什么区别?
void foo(int [*]);和
void foo(int []);
谢谢.
解决方法
您不能在C89 / 90中使用数组声明的类型限定符或静态大小部分.这些功能特定于C99.
数组声明中的static告诉编译器,您承诺指定数量的元素将始终作为实际参数传递的数组中存在.这可能有助于编译器生成更有效的代码.如果您在实际代码中违反了您的承诺(即传递较小的数组),则行为是未定义的.例如,
void foo(int a[static 3]) { ... } int main() { int a[4],b[2]; foo(a); /* OK */ foo(b); /* Undefined behavior */ }
数组声明的*大小部分仅在函数原型声明中使用.它表示数组具有可变长度(VLA).例如,在功能定义中,您可以使用具体运行时大小的VLA
void foo(int n,int a[n]) /* `a` is VLA because `n` is not a constant */ { ... }
当您声明原型时,您可以做同样的事情
void foo(int n,int a[n]); /* `a` is VLA because `n` is not a constant */
但是如果不指定参数名称(在原型中可以),那么当然不能使用n作为数组大小.然而,如果您仍然要告诉编译器该阵列将是一个VLA,您可以使用*来实现该目的
void foo(int,int a[*]); /* `a` is VLA because size is `*` */
注意,具有1D阵列的示例不是一个好的例子.即使你省略了*并声明了上述的功能
void foo(int,int a[]);
那么代码仍然可以正常工作,因为在函数参数声明中,数组类型反而用指针类型隐含地替换.但一旦开始使用多维数组,正确使用*变得很重要.例如,如果函数被定义为
void bar(int n,int m[n][n]) { /* 2D VLA */ ... }
原型可能如下所示
void bar(int n,int m[n][n]); /* 2D VLA */
或作为
void bar(int,int m[*][*]); /* 2d VLA */
在后一种情况下,第一个*可以省略(因为数组到指针的替换),而不是第二个*.