ANSI-C语法 – 像[*]等的数组声明

来自 -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 */

在后一种情况下,第一个*可以省略(因为数组到指针的替换),而不是第二个*.

相关文章

本程序的编译和运行环境如下(如果有运行方面的问题欢迎在评...
水了一学期的院选修,万万没想到期末考试还有比较硬核的编程...
补充一下,先前文章末尾给出的下载链接的完整代码含有部分C&...
思路如标题所说采用模N取余法,难点是这个除法过程如何实现。...
本篇博客有更新!!!更新后效果图如下: 文章末尾的完整代码...
刚开始学习模块化程序设计时,估计大家都被形参和实参搞迷糊...