数组类型规范中的 const / static / 易失性?

Kev*_*ier 7 c c11

下面的函数签名在 C 中定义了什么?!

#include <stdio.h>
#include <string.h>

void f(int a[const volatile static 2])
{
    (void)a;
}

int main() {
    int b[1];
    f(b);
}
Run Code Online (Sandbox Code Playgroud)

https://godbolt.org/z/6qPxaM1vM

这个地方我不明白const//volatile的含义,但是它似乎可以编译,所以我猜它有一个含义?static

谢谢

Lun*_*din 5

这是 C99 中引入的一个比较有用的功能。从 C17 6.7.6.3/7 开始:

\n
\n

将参数声明为 \xe2\x80\x9d 类型的 \xe2\x80\x9c 数组应调整为 \xe2\x80\x9c 指向类型 \xe2\x80\x9d 的限定指针,其中\n类型限定符(如果有)为在数组类型派生的 [ 和 ] 中指定的那些。如果关键字static也出现在数组类型派生的 [ 和 ] 中,则对于每次调用该函数,相应实际参数的值应提供对具有至少相同数量元素的数组的第一个元素的访问由尺寸表达式指定。

\n
\n

在这种情况下,限定符constvolatile意味着数组衰减为类型的指针int* const volatile a。由于此限定类型对于函数来说是本地的,因此对于调用者来说意义不大,因为传递的指针是通过左值转换分配的,并且仍然可以是非限定指针类型。

\n

static稍微有用一些,因为它据说可以让编译器进行一些编译时大小检查,尽管实际上主流编译器(当前)似乎只能检查指针是否不为空。例如,f(0)在 clang 上给出:

\n
\n

警告:null 传递给需要非空参数的被调用者 [-Wnonnull]

\n
\n

奇怪的是,f(0)在 gcc 11.1 及更高版本上说:

\n
\n

警告:“int[static 8]”的参数 1 为 null,预期为非空 [-Wnonnull]”

\n
\n

不知道它8来自什么,我猜这是一个拼写错误/小编译器错误(腐烂的指针有 8 个字节大)。

\n