数组声明语法

Array declaration syntax

我对 C99 标准中的数组声明有一些疑问。

int n;

scanf("%d", &n);

int v[n];

这会创建一个大小不同的数组吗?我知道它可以是常量或常量变量。但我认为它必须在编译时有一个已知值,并且大小不应该改变。

但是我多次看到上面提到的语法,我不知道这是一个防御性错误。

第二个问题是关于传递给函数的数组。

void printing(int v[])

void printing(int *v)

两种声明有区别吗?

C99 引入了对可变修改 (VM) 类型的支持。这些类型包含直到运行时才知道的参数。 该行:

int v[n];

创建一个数组类型的自动变量,其大小在运行时定义。这些对象称为可变长度数组 (VLA)。

这是一个有效的 C99 语法,尽管它被认为是一种冒险的做法,因为分配 any 自动对象的机制不提供任何错误检测。这对于编译时大小未知的自动 VLA 尤其成问题。 自动对象通常分配在堆栈上,这是一种稀缺资源(通常在托管机器上为几 MiB,在嵌入式系统上为千字节)。

此外,如果 n 为非正数,则会发生未定义行为。

关于你的第二个问题,声明如下:

void printing(T v[]);
void printing(T *v);

通常是等价的,因为数组类型的参数类型会自动调整为指针类型。例如int v[]int v[10]调整为int*float A[10][10]调整为float (*A)[10].

尽管有一些不同:

  • T在组成T *v时可以不完整,但在使用数组类型时必须完整。
struct S; // incomplete type
void foo(struct S *s); // ok
void foo(struct S s[]); // error
  • 可以使用 static 关键字
  • 告诉编译器数组 v 的最小元素数
void foo(int v[static 10]);

编译器可以假定对 v[0]...v[9] 的访问是有效的。

void foo(int v[static 1]);

告诉编译器 v 不为 NULL。