一个非常简单的 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
关键字的用途是什么(顺便说一句,这个构造的名称是什么?)?
static
向优化器指示(提示 - 但不超过提示)它可能假设存在最少的适当数量(在示例中为 5 个)元素在数组中(因此数组指针也不为空)。这也是对使用函数的程序员的指示,他们必须将足够大的数组传递给函数以避免未定义的行为。
ISO/IEC 9899:2011
§6.7.6.2 Array declarators
Constraints
¶1 In addition to optional type qualifiers and the keyword static
, the [
and ]
may delimit
an expression or *
. If they delimit an expression (which specifies the size of an array), the
expression shall have an integer type. If the expression is a constant expression, it shall
have a value greater than zero. The element type shall not be an incomplete or function
type. The optional type qualifiers and the keyword static
shall appear only in a
declaration of a function parameter with an array type, and then only in the outermost
array type derivation.
§6.7.6.3 Function declarators (including prototypes)
¶7 A declaration of a parameter as "array of type" shall be adjusted to "qualified pointer to
type", where the type qualifiers (if any) are those specified within the [
and ]
of the
array type derivation. If the keyword static
also appears within the [
and ]
of the
array type derivation, then for each call to the function, the value of the corresponding
actual argument shall provide access to the first element of an array with at least as many
elements as specified by the size expression.
您的代码会崩溃,因为如果您将空指针传递给需要数组的函数(保证它是包含 5 个元素的数组的开头)。您正在调用未定义的行为,崩溃是处理您的错误的一种非常明智的方式。
当您将一个包含 3 个整数的数组传递给一个保证包含 5 个整数的数组的函数时,情况会更加微妙;同样,您调用未定义的行为并且结果是不可预测的。崩溃的可能性相对较小;虚假结果的可能性很大。
实际上,此上下文中的 static
有两个独立的工作——它定义了两个独立的契约:
- 它告诉函数的用户他们必须提供至少包含 5 个元素的数组(如果他们不这样做,他们将调用未定义的行为)。
- 它告诉优化器它可能会假定一个指向至少包含 5 个元素的数组的非空指针,并且它可能会相应地进行优化。
如果函数的用户违反了函数的要求,一切都可能会崩溃(“鼻恶魔”等;通常是未定义的行为)。