C99中数组的静态大小

Jos*_* MN 5 c arrays gcc c99

一个非常简单的C程序:

#include <stdio.h>
#include <stdlib.h>

void process(int array[static 5]){
    int i;
    for(i=0; i<5; i++)
        printf("%d ", array[i]);
    printf("\n");
}

int main(){

    process((int[]){1,2,3});
    process(NULL);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我编译它: gcc -std=c99 -Wall -o demo demo.c

确实编译,当我运行它时,它崩溃(非常可预测).

为什么?static数组参数中关键字的用途是什么(这个构造的名称是什么btw?)?

Jon*_*ler 8

优化器static有一个指示(一个提示 - 但不超过一个提示)它可能假设数组中有一个最小的适当数字(在例子中为5)元素(因此数组指针是也不是空的).它也是程序员使用函数的指令,它必须将足够大的数组传递给函数以避免未定义的行为.

ISO/IEC 9899:2011

§6.7.6.2数组声明符

约束
1除了可选的类型限定符和关键字之外static,[]可以分隔表达式或*.如果它们分隔表达式(指定数组的大小),则表达式应具有整数类型.如果表达式是常量表达式,则其值应大于零.元素类型不应是不完整或函数类型.可选的类型限定符和关键字static只出现在具有数组类型的函数参数的声明中,然后仅出现在最外层的数组类型派生中.

§6.7.6.3函数声明符(包括原型)

7的参数为"类型的阵列"的声明,应调整为"合格指针输入",其中类型限定符(如果有的话)的那些内的指定[]该阵列类型的推导.如果关键字static也出现在数组类型派生的[]中,那么对于每次对函数的调用,相应的实际参数的值应该提供对数组的第一个元素的访问,其中至少有与该大小指定的元素一样多的元素.表达.


您的代码崩溃,因为如果您将空指针传递给期望数组的函数(保证是5个元素的数组的开头),您将调用未定义的行为,崩溃是处理您的错误的一种非常明智的方法.

将3个整数的数组传递给保证5个整数数组的函数时,它会更加微妙; 再次,您调用未定义的行为,结果是不可预测的.崩溃的可能性相对较小; 虚假结果非常可能.

实际上,static在此上下文中有两个单独的作业 - 它定义了两个单独的合同:

  1. 它告诉用户该函数必须提供至少5个元素的数组(如果不这样做,它们将调用未定义的行为).
  2. 它告诉优化器它可以假定一个非空指针指向至少5个元素的数组,并且它可以相应地进行优化.

如果该函数的用户违反了该函数的要求,那么所有地狱都可能会崩溃('鼻子恶魔'等;通常是未定义的行为).