C 中参数数组类型中的“静态”是什么意思?

Des*_*tor 2 arrays parameters static function c99

我看到了以下一些复杂的函数定义。

void foo(double A[static 10]) {
   double B[10];    
}
Run Code Online (Sandbox Code Playgroud)

它是有效的 C 和 C++ 代码吗?它是 C99 或 C++ 标准引入的新语法吗?它的目的是什么?我应该什么时候使用它?这有什么必要?

Pas*_*uoq 5

这种 C99 符号 ,void foo(double A[static 10])意味着该函数可以假定A指向 10 个有效参数(从*AA[9])。该符号使程序信息量更大,帮助编译器优化为函数生成的代码foo并检查它是否在每个调用点被正确调用。

在引入符号的 C99 标准中,第 6.7.5.2 和 6.7.5.3:7 条涵盖了这一点。

“……如果关键字 static 也出现在数组类型派生的 [ 和 ] 中,那么对于函数的每次调用,相应实参的值应提供对具有至少相同元素的数组的第一个元素的访问由大小表达式指定”


一种常见的用法是f(int p[static 1]),它或多或少等同于其他语言中的引用(相对于指针)的概念。如果声明了这样的函数并在调用站点处传递了一个空指针,Clang 会发出警告(因为该符号明确表示p不会是NULL)。但是,上次我尝试时,Clang 没有警告 for f(&a + 1),这是一种耻辱(但编译器不必发出所有警告。发出一些警告已经很好了):

#include <stdio.h>

void f(int p[static 1])
{
  printf("%d\n", *p);
}

int main(){
  int a = 0;
  f(&a + 1);
  f(0);
  f(&a);
}
Run Code Online (Sandbox Code Playgroud)

Clang 对第二个调用发出警告,但不幸的是第一个调用没有警告:

$叮当tc
tc:11:3: 警告:null 传递给需要非空参数的被调用方
      [-Wnonnull]
  f(0);
  ^ ~
tc:3:12: 注意:被调用者在此处将数组参数声明为静态
void f(int p[静态 1])
           ^~~~~~~~~~~
已生成 1 个警告。

语法可能看起来有点奇怪,但 C99 标准化委员会显然决定static在不会引起歧义的地方重用预先存在的关键字,以避免引入新的关键字(可能会破坏现有程序)。