C参数数组声明符

ale*_*cov 15 c arrays parameters syntax function

在C99中有变长数组,参数数组声明符中可以有静态限定符(和类型限定符):

void f(int i, int *a);
void f(int i, int a[]);
void f(int i, int a[i]);
void f(int i, int a[*]);         // Only allowed in function prototypes.
void f(int i, int a[static i]);
Run Code Online (Sandbox Code Playgroud)

由于数组函数参数只是衰减到指针,以前的声明之间是否有任何实际差异,还是风格问题?什么时候应该使用它们?特别是,static限定词意味着什么?该标准没有清楚地说明每种语法的原因.

AnT*_*AnT 24

只要您只使用一维数组,上述声明都是等效的.最后一个

void f(int i, int a[static i])
Run Code Online (Sandbox Code Playgroud)

有额外的效果.它在参数类型方面等同于先前的参数类型,但也告诉编译器它可以依赖于a指向至少i元素的数组的参数(可以在优化中使用).

你也忘了另一个新的宣言

void f(int i, int a[const])
Run Code Online (Sandbox Code Playgroud)

即使在单维阵列的情况下,这个实际上确实具有效果.它相当于

void f(int i, int *const a)
Run Code Online (Sandbox Code Playgroud)

虽然有些人可能认为功能参数的常量资格是无用的.在使用[]声明语法之前,无法对指针进行const限定之前,数组参数会"衰减" .

*(以及i之间)[]开始仅当所述第二(或更大)对之间使用无关紧要[]在多维数组宣言.从本质上讲,它就像它一直以来一样:参数声明中的数组大小始终只在第二对或另一对之间起作用[].将*在原型声明的VLA参数一起使用,当尺寸值没有被明确命名.例如,您可以声明

void bar(int n, int m, int a[n][m]);
Run Code Online (Sandbox Code Playgroud)

并且编译器将知道这a是一个VLA,因为大小不是常量.但是如果您不想在原型中命名参数,那么您如何告诉编译器a是VLA?那是有*帮助的

void bar(int, int, int a[*][*]);
Run Code Online (Sandbox Code Playgroud)

  • 非常感谢您的澄清.我首先怀疑`static`限定符与优化问题有关.另外,你忘了提到任何类型限定符都可以在数组声明符中声明,并且它们可能扮演一个非常重要的角色(例如`restrict`或`volatile`)而不是`const`本身. (2认同)
  • @supercat:`void func1(int a[-1])`是非法的。负数组大小在所有上下文中都是非法的。`void func2(int a[some_global++]);` 被替换为 `void func2(int a[*]);` 并且相当于 *函数原型* 中的 `void func2(int *a)`。在函数*定义*中,这会将“a”声明为相应大小的VLA,并且*将*在每次调用该函数时递增“some_global”。 (2认同)