【问题标题】:Array declaration syntax数组声明语法
【发布时间】:2021-12-20 09:17:05
【问题描述】:

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

int n;

scanf("%d", &n);

int v[n];

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

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

第二个问题与传递给函数的数组有关。

void printing(int v[])

void printing(int *v)

这两种声明有区别吗?

【问题讨论】:

标签: c c99


【解决方案1】:

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。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-09-18
    • 2018-01-07
    • 1970-01-01
    • 2017-01-07
    • 2020-05-03
    • 2011-01-03
    • 2015-06-08
    • 1970-01-01
    相关资源
    最近更新 更多