C99中数组的静态大小

时间:2013-08-21 16:00:13

标签: 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;
}

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

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

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

2 个答案:

答案 0 :(得分:8)

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

  

ISO / IEC 9899:2011

     

§6.7.6.2数组声明符

     

<强>约束
  ¶1除了可选的类型限定符和关键字static之外,[]可能会划界   表达式或*。如果它们分隔表达式(指定数组的大小),则   表达式应具有整数类型。如果表达式是常量表达式,它应该是   值大于零。元素类型不应是不完整或功能   类型。可选的类型限定符和关键字static只能出现在   声明具有数组类型的函数参数,然后仅在最外层   数组类型推导。

     

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

     

¶7参数声明为“类型数组”应调整为“合格指针”   type“,其中类型限定符(如果有)是在[]中指定的类型限定符。   数组类型推导。如果关键字static也出现在[]内   数组类型派生,然后对每个函数调用,对应的值   实际参数应提供对至少具有至少数量的数组的第一个元素的访问   由size表达式指定的元素。


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

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

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

  1. 告诉用户该函数必须提供至少5个元素的数组(如果没有,则会调用未定义的行为)。
  2. 它告诉优化器它可以假定一个非空指针指向至少5个元素的数组,并且它可以相应地进行优化。
  3. 如果该功能的使用者违反了该功能的要求,那么一切都可能会破裂(“鼻子恶魔”等;通常是未定义的行为)。

答案 1 :(得分:1)

您的代码是正确的(实际建议...参见C99,N1124 / 1256,第6.7.5.3-7条(参见Jonathan的全文):

  

如果关键字static也出现在数组的[和]中   类型派生,然后对每个函数的调用,值的   相应的实际参数应提供对第一个的访问权限   数组的元素,其元素至少与指定的元素一样多   大小表达。

错误是您的数组定义 - 您将其分配为容纳3个元素,但随后您调用需要五个元素的函数(通过[static 5]),从而触发崩溃。