数组声明语法
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。
我对 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。