2

这两种形式的数组声明是否正确?

第一的:

int n;
n=3;
int A[n];

第二:

#define N 300;
.
.
.
.
int a[N];

对我来说,这两种方法是完全有效的,但有人告诉我第一种是错误的。

第一个就像说:

int A[10];

所以,对我来说,说第一个无效并没有多大意义。

但为了完全确定,我想在这里问它。它只是关于编程风格还是第一个不是正确的方法?

谢谢你。

4

3 回答 3

6

您的第一个示例使用称为可变长度数组( VLA ) 的 C99 功能,这在草案 C99 标准部分6.7.5.2 Array declarators 第 4 段中有所介绍:

[...]如果大小是整数常量表达式并且元素类型具有已知的常量大小,则数组类型不是可变长度数组类型;否则,数组类型是可变长度数组类型。

这两种形式都不一定不好,但是如果可以通过用户输入来控制可变长度数组的大小,则它们可能会很危险。主要问题是并非所有编译器都支持 C99,最好的例子是Visual Studio,尽管据我所知它最近开始支持 C99的部分内容,但它仍然不支持 VLA。如果你想在 C++ 中使用你的代码也是一个问题,因为 C++ 标准根本不支持 VLA,但gccclang支持 VLA 作为 C++ 中的扩展。请注意,VLA 是为 C++14 提出的,但被拒绝了。

另一个问题是 C11 使 VLA 成为可选功能,这在C11 草案标准部分6.10.8.3 Conditional feature macros中有介绍:

_ _STDC_NO_VLA_ _   The integer constant 1, intended to indicate that the
                    implementation does not support variable length arrays or
                    variably modified types.
于 2014-08-31T02:09:40.823 回答
2

根据 C99 ISO 可变长度数组是有效的。GCC 手册说

Variable-length automatic arrays are allowed in ISO C99, and as an extension GCC accepts them in C90 mode and in C++

gcc:可变长度

于 2014-08-31T02:03:43.150 回答
1

两种变体都有其优点和缺点:


可变长度数组的优点:

  • 你不会浪费内存。您可以根据需要简单地分配尽可能多的内存。这在字符串中最为明显:通常,您希望允许非常长的字符串,即使大多数字符串非常非常短。为所有字符串分配 0.5 KB 是对内存的巨大浪费,即使分配较少可能已经是一个太紧的约束。

  • 你没有引入人为的限制。由于您可以根据动态需要精确地分配内存,因此您不会对用户的名称/路径/文件/任何内容的长度施加上限。

可变长度数组的缺点:

  • 您不能在堆栈上分配任意大的数组。即使您的系统可以自动增加您的堆栈,您仍然可以通过分配一个数组来对您的程序进行段错误,该数组使堆栈指针跨越操作系统使用的标记页。几千字节通常可以,几兆字节则不行。

固定大小缓冲区的优点:

  • 易于设置。

  • 它们是 C++。C++11 标准明确禁止数组类型具有运行时大小,即使 C 甚至允许您从 C9​​9 开始对可变长度数组进行类型定义(void foo(int n) { typedef int (*)[n]; ... }完全合法的 C99,但您不能用void foo(int n) { int bar[n]; }C++11 编写)。

固定大小缓冲区的缺点:

  • 它们往往会给用户带来固定限制的负担。当然,您可以尝试处理通常需要更多内存的情况,但在大多数情况下,这些限制只是转发给有一天会对此非常不满的用户。

  • 他们通过缓冲区溢出来引入错误。您的程序需要明确且正确地处理由于超出数组大小而导致的所有错误。此错误处理代码中的一个错误,您的程序以一种可能是安全漏洞的方式崩溃。使用可变长度数组,您永远不会遇到超出缓冲区的情况,因为您总是为工作分配足够大的缓冲区。


总而言之,我相信#define N ...而且int foo[N];几乎总是不好的风格。如果您可以证明最大大小较小并且您没有编写 C++,请使用可变长度数组。如果你不能malloc()/new数组。只有当你能证明你永远不会需要超过一个非常特定的大小(如“四次根求解器永远不会返回超过四个根”)时,才能继续使用固定大小。malloc()就个人而言,我用/分配了几乎所有的数组new

于 2014-08-31T14:23:01.770 回答