这个问题与"Are conformant array parameters VLAs?"非常相似,唯一的区别是我在数组声明的[]中使用了static关键字(在C99中引入),这意味着声明的数组应该至少有len个元素的空间.下面是一个例子:

#include <stddef.h>
#include <stdio.h>

void print_array(size_t len, const int arr[static len]) {
    for (size_t i = 0; i < len; i++) {
        printf("%d\n", arr[i]);
    }
}

int main(void) {
    const int arr[] = {1, 2, 3, 4};
    print_array(sizeof arr / sizeof *arr, arr);
    return 0;
}

当在GCC和Clang上使用-Wvla标志编译此代码时,会给出以下警告:

main.c:4:1: warning: ISO C90 forbids variable length array ‘arr’ [-Wvla]
    4 | void print_array(size_t len, const int arr[static len]) {
      | ^~~~

即使在指定static的情况下,arr作为VLA的意义是什么?这难道不会让static对这样的案件毫无用处吗?

我试着在C标准中寻找答案,但我找不到.

谢谢!

推荐答案

GCC关于这是一名VLA的说法是正确的吗?

C 2018(和C 2011)6.7.6.2 4表示,数组声明符:

…如果大小是整数常量表达式,并且元素类型具有已知的常量大小,则数组类型不是variable length array类型;否则,数组类型是可变长度数组类型.

在声明const int arr[static len]中,len不是整数常量表达式,因此数组类型是可变长度数组类型.所以GCC是对的.

即使在指定静态的情况下,arr作为VLA也有什么意义?

6.7.6.3 7表示:

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

编译器如何使用这一点的一个例子是,如果函数体包含求值表达式arr[i],其中arr已经用const int array[static len]声明,则编译器可以假定ilen,并且它可以基于此进行优化.

这难道不会让static在这样的情况下毫无用处吗?

不,尽管如果编译器不利用这些信息,我也不会感到惊讶.

C++相关问答推荐

C strlen on char array

为什么复合文字(C99)的返回会生成更多的汇编代码?

特定闪存扇区的内存别名

struct 上的OpenMP缩减

为什么STM32G474RE上没有启用RCC PLL

C++中矢量类型定义和数据保护的高效解决方案

在C++中通过空指针隐式访问常量变量的值

GCC奇怪的行为,有fork 和印花,有换行符和不换行符

无法访问共享目标文件内的共享指针

如何将C中的两个字符串与从文件接收的字符串中的字符数进行比较

我在C程序的Flex/Bison中遇到语法错误

CS50判断灯泡运动的问题,判断时多出一个灯泡,但不在终端上

为什么Linux无法映射这个PT_LOAD ELF段?

某些EAX值的不同调用方的CPUID结果不一致

可以对两种 struct 类型中的任何一种进行操作的C函数

将不同类型的指针传递给函数(C)

当另一个指向 const 的指针观察到数据时,通过指针更改数据是否安全?

根据输入/输出将 C 编译过程分为预处理、编译、汇编和链接步骤

保存有符号整数结果的变量是否会溢出(后增量的副作用),并且此后从未在任何表达式中使用过它,是否会导致 UB?

C simd _m128 晶圆厂