这两种形式的数组声明是否正确?
首先:
int n;
n=3;
int A[n];
第二
#define N 300;
.
.
.
.
int a[N];
对我而言,这两种方式完全有效,但有人告诉我第一种方式是错误的。
第一个就像是说:
int A[10];
所以,对我而言,说第一个无效是没有意义的。
但要完全确定,我想在这里问一下。它只是关于编程风格还是第一个不正确的方式?
谢谢。
答案 0 :(得分:6)
您的第一个示例使用名为variable length arrays( VLA )的C99功能,draft C99 standard部分6.7.5.2
数组声明符第4段中对此进行了介绍:
[...]如果size是一个整型常量表达式,并且元素类型具有已知的常量大小,则数组类型不是可变长度数组类型; 否则,数组类型是可变长度数组类型。
两种形式都不一定是坏的,但如果可以通过用户输入控制它们的大小,则可变长度数组可能是危险的。主要问题是并非所有编译器都支持C99,最好的例子是Visual Studio,尽管recently started supporting parts of C99据我所知仍然不支持VLA。如果你想在C ++中使用你的代码也是一个问题,因为C ++标准根本不支持VLA,尽管gcc和clang支持VLA作为C ++中的扩展。请注意,VLA是针对C ++ 14提出的,但被拒绝了。
另一个问题是C11使VLA成为可选功能,C11 draft standard部分6.10.8.3
条件功能宏涵盖了这一点:
_ _STDC_NO_VLA_ _ The integer constant 1, intended to indicate that the implementation does not support variable length arrays or variably modified types.
答案 1 :(得分: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++
答案 2 :(得分:1)
两种变体都有其优点和缺点:
可变长度阵列的优点:
你不浪费记忆。您可以根据需要分配尽可能多的内存。这在字符串中最为明显:通常,您希望允许非常长的字符串,即使大多数字符串确实很短。为所有字符串分配半千字节是一个巨大的内存浪费,即使分配较少的内容可能已经太严格了。
您没有引入人为限制。由于您精确分配了动态所需的内存,因此不会给用户带来名称/路径/文件/可能存在的上限的上限。
可变长度阵列的缺点:
固定大小缓冲区的优点:
易于设置。
他们是C ++。 C ++ 11标准明确禁止数组类型具有运行时大小,即使C甚至允许您键入自定义可变长度数组,因为C99(void foo(int n) { typedef int (*)[n]; ... }
是完全合法的C99,但你不能写C ++中的void foo(int n) { int bar[n]; }
11)。
固定大小缓冲区的缺点:
他们倾向于给用户带来固定限制。当然,您可以尝试处理通常需要更多内存的情况,但在大多数情况下,这些限制只会转发给有一天会对此非常不满的用户。
他们通过缓冲区溢出来引发错误。您的程序需要明确正确地处理因超出数组大小而导致的所有错误。此错误处理代码中的一个错误,您的程序崩溃的方式很可能是一个安全漏洞。对于可变长度数组,您永远不会遇到超出缓冲区的情况,因为您总是将缓冲区分配给该作业足够大。
总而言之,我相信#define N ...
和int foo[N];
几乎总是糟糕的风格。如果你可以证明一个较小的最大尺寸并且你没有编写C ++,那么请使用可变长度数组。如果你不能malloc()
/ new
数组。只有当你能够证明你永远不能要求超过一个非常特定的大小时(例如在"四次根求解器永远不会返回超过四个根和#34;),继续使用固定大小。就个人而言,我使用malloc()
/ new
分配几乎所有数组。