标签: variable-length-array

无论如何,VLA有什么意义?

我理解变量长度数组是什么以及它们是如何实现的.这个问题是关于他们存在的原因.

我们知道VLA只允许在功能块(或原型)中使用,并且它们基本上不能在堆栈上的任何地方(假设正常实现):C11,6.7.6.2-2:

如果标识符被声明为具有可变修改类型,则它应该是普通标识符(如6.2.3中所定义),没有链接,并且具有块范围或函数原型范围.如果标识符被声明为具有静态或线程存储持续时间的对象,则它不应具有可变长度数组类型.

我们举一个小例子:

void f(int n)
{
    int array[n];
    /* etc */
}
Run Code Online (Sandbox Code Playgroud)

有两种情况需要注意:

  • n <= 0:f必须防范这一点,否则行为是不明确的:C11,6.7.6.2-5(强调我的):

    如果size是一个不是整数常量表达式的表达式:如果它出现在函数原型范围的声明中,则将其视为替换为*; 否则, 每次评估它时,其值应大于零.可变长度数组类型的每个实例的大小在其生命周期中不会改变.如果size表达式是运算sizeof符操作数的一部分,并且更改size表达式的值不会影响运算符的结果,则无法指定是否计算size表达式.

  • n > stack_space_left / element_size:没有标准的方法可以找到剩余多少堆栈空间(因为只要涉及标准就没有堆栈这样的东西).所以这个测试是不可能的.只有明智的解决方案才是拥有预定义的最大可能大小n,例如N,确保不会发生堆栈溢出.

换句话说,程序员必须确保0 < n <= N一些N选择.但是,程序应该n == N仍然可以工作,所以人们也可以声明数组的大小N是常量而不是可变长度n.

我知道引入了VLA以替换alloca(在本回答中也提到过),但实际上它们是相同的(在堆栈上分配可变大小的内存).

所以问题是为什么allocaVLA存在并且因此VLA存在以及它们为什么不被弃用?在我看来,使用VLA的唯一安全方法是使用有限大小,在这种情况下,采用具有最大大小的正常阵列始终是可行的解决方案.

c variable-length-array

12
推荐指数
4
解决办法
8382
查看次数

在gcc中将2D数组初始化为0时,值不正确

#include <iostream>
using namespace std;

int main() {

    int rows = 10;
    int cols = 9;
    int opt[rows][cols] = {0};

         for (int i = 0; i < rows; ++i) {
            for (int j = 0; j < cols; ++j) {
                std::cout << opt[i][j] << " ";
            }
             std::cout << "\n";
         }

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出:

0 32767 1887606704 10943 232234400 32767 1874154647 10943 -1 
0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 …
Run Code Online (Sandbox Code Playgroud)

c++ gcc variable-length-array

12
推荐指数
2
解决办法
654
查看次数

C99型VLA有哪些技术缺点?

我从许多人那里听说,在C99中引入的可变长度阵列非常糟糕.IRC的一些人在一分钟之前说过"我不认为C++会得到VLA,而strousoup对他们做了一些非常负面的评论".

这些人讨厌VLA的原因是什么?

c c++ c99 variable-length-array c++11

11
推荐指数
3
解决办法
1457
查看次数

如何在C99运行时计算可变长度数组的大小?

在C89中,数组的长度在编译时是已知的.但是在C99中,对于可变长度数组,在运行之前,数组的长度可能是未知的.

那怎么计算呢?

为什么不能以相同的方式计算动态分配的数组的长度?

c arrays c99 variable-length-array ansi-c

11
推荐指数
2
解决办法
1455
查看次数

未记载的GCC扩展:结构中的VLA

在阅读Clang文档时,我遇到了以下有趣的消息:[1]

clang不支持允许结构中的可变长度数组的gcc扩展.这有几个原因:一,实施起来很棘手,二,扩展完全没有文档,三,扩展似乎很少使用.请注意,clang确实支持灵活的数组成员(在结构末尾具有零或未指定大小的数组).

如何使用此扩展?我的理解是在构造函数中使用alloca会导致堆栈指针在调用函数的末尾被恢复,在这种情况下,它将是构造函数 - 而不是在封闭结构的末尾.

谢谢您的帮助!

c++ memory gcc g++ variable-length-array

10
推荐指数
1
解决办法
2633
查看次数

可变修改类型兼容性及其安全隐患

我对C99的可变修改型系统感兴趣.这个问题的灵感来自于这个问题.

检查这个问题的代码,我发现了一些有趣的东西.考虑以下代码:

int myFunc(int, int, int, int[][100]);

int myFunc(int a, int b, int c, int d[][200]) {
    /* Some code here... */
}
Run Code Online (Sandbox Code Playgroud)

这显然不会(也不会)编译.但是,这段代码:

int myFunc(int, int, int, int[][100]);

int myFunc(int a, int b, int c, int d[][c]) {
    /* Some code here... */
}
Run Code Online (Sandbox Code Playgroud)

编译甚至没有警告(在gcc上).

这似乎意味着可变修改的阵列类型与任何非可变修改的阵列类型兼容!

但那还不是全部.您期望一种可变修改类型至少可以使用哪个变量来设置其大小.但它似乎没有这样做!

int myFunc(int, int b, int, int[][b]);

int myFunc(int a, int b, int c, int d[][c]) {
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

也编译没有任何错误.

所以,我的问题是:这是正确的标准化行为吗?

此外,如果一个可变修改的数组类型真的与任何具有相同维度的数组兼容,那么这不会意味着令人讨厌的安全问题吗?例如,请考虑以下代码:

int myFunc(int a, int b, int c, int …
Run Code Online (Sandbox Code Playgroud)

c gcc c99 variable-length-array

10
推荐指数
1
解决办法
118
查看次数

将可变长度数组声明为C中的全局变量

如何将可变长度数组声明为全局变量?

当在扫描长度之前在函数中声明可变长度数组时,它会编译但不会运行.它给出了分段错误.当相同的声明语句转移到扫描语句下方时,它运行正常.

如果我们想要一个可变长度数组全局可用于所有函数,我们该怎么做?这里的问题是数组的长度只能通过某些函数进行扫描.

c global-variables variable-length-array

9
推荐指数
1
解决办法
8362
查看次数

为什么零长度VLA UB?

2011年标准明确规定......

6.7.6.2数组声明符

  1. 如果size是一个不是整数常量表达式的表达式:如果它出现在函数原型范围的声明中,则将其视为替换为 *; 否则,每次评估它时,其值应大于零.可变长度数组类型的每个实例的大小在其生命周期中不会改变.如果size表达式是运算sizeof符操作数的一部分,并且更改size表达式的值不会影响运算符的结果,则无法指定是否计算size表达式.

这是设计,但以下代码似乎是合理的.

size_t vla(const size_t x) {

  size_t a[x];
  size_t y = 0;

  for (size_t i = 0; i < x; i++)
    a[x] = i;

  for (size_t i = 0; i < x; i++)
    y += a[i % 2];

  return y;
}
Run Code Online (Sandbox Code Playgroud)

Clang似乎为它生成合理的x64程序集(没有优化).显然索引零长度VLA没有意义,但访问超出边界会调用未定义的行为.

为什么零长度数组未定义?

c arrays variable-length-array

9
推荐指数
2
解决办法
224
查看次数

关于sizeof溢出size_t的C标准

这是未定义的行为吗?标准的相关部分并没有多说。

size_t n = SIZE_MAX / sizeof(double) + 1;
size_t m = sizeof(double[n]);
Run Code Online (Sandbox Code Playgroud)

c sizeof language-lawyer variable-length-array

9
推荐指数
1
解决办法
144
查看次数

为什么全局数组大小应该是整数常量?

在 C++ 中,我尝试声明某个大小的全局数组。我得到了错误:

数组绑定不是 ']' 标记之前的整数常量

但是当我在main()函数中声明一个相同类型的数组时,它工作正常。

为什么这里有不同的行为?

int y=5;
int arr[y];         //When I comment this line it works fine

int main()
{
    int x=5;
    int arr2[x];        // This line doesn't show any error.
}
Run Code Online (Sandbox Code Playgroud)

编辑:许多人认为这个问题是重复获取错误 "array bound is not an integer constant before ']' token"。但是这个问题并没有回答为什么会有不同的行为。

c++ variable-length-array

8
推荐指数
1
解决办法
472
查看次数