使用可变长度数组有一些开销吗?可以在运行时通过命令行参数传递数组的大小吗?与自动和动态分配数组相比,为什么会引入它?
您可能知道,VLA 有优点也有缺点,并且在 C11 中它们是可选的。
我认为使 VLA 成为可选的主要原因是:“堆栈可能会爆炸”:
int arr[n]; /* where n = 1024 * 1024 * 1024 */
Run Code Online (Sandbox Code Playgroud)
但是指向 VLA 的指针又如何呢?
int m, n;
scanf("%d %d", &m, &n);
int (*ptr)[n] = malloc(sizeof(int [m][n]));
Run Code Online (Sandbox Code Playgroud)
在这种情况下,不存在炸毁堆栈的风险,而且在我看来它们非常有用。
我的问题是:
委员会是否可以保留指向 VLA 的指针,从而使指向非指针类型的 VLA 成为可选?
或者一件事暗示另一件事?
(原谅我糟糕的英语)
这个问题涉及但来自不同这一个约在C99可变长度数组.
答案指出,在堆栈中分配可变长度数组(或者只是固定大小的大数组)的一个危险是分配可能会无声地失败,而不是调用malloc,这显然告诉调用者分配是否成功.
现代非嵌入式编译平台使用无效的内存区域来检测一些堆栈溢出,而无需额外成本(检查只是MMU已经免费进行的检查).这不能保证100%免受上述问题的影响,因为非常大的本地数组可能导致堆栈指针跳过无效区域.
有没有人知道通常会为此检测分配多少页?我想这至少是4KiB,但它可能会更多.这是由编译器或操作系统做出的选择,在任何一种情况下,有没有办法改变它?
我想创建用户指定的一些线程.我为此编写的代码是:
int nhijos = atoi(argv[1]);
thread = malloc(sizeof(pthread_t)*nhijos);
for (i = 0; i < nhijos; i++){
if (pthread_create ( &thread[i], NULL, &hilos_hijos, (void*) &info ) != 0){
perror("Error al crear el hilo. \n");
exit(EXIT_FAILURE);
}
Run Code Online (Sandbox Code Playgroud)
它是否正确?
根据这个答案,其中指出:
编译器知道int类型的大小,因此可以生成正确的汇编程序指令,该指令将在堆栈上保留足够的空间,以便让foo存在.
编译器需要知道函数将在堆栈上占用的大小才能实现它.
那么,为什么这段代码会编译?
int f(int n)
{
int x[n];
}
int main()
{
f(3);
f(5);
//etc
}
Run Code Online (Sandbox Code Playgroud)
x 是一个整数数组,但它的大小不是常量,它可以在调用函数的任何时候改变.
我在这里错过了什么?
我正在通过88 C程序工作,在将近二十五年之后重新学习C(由于自1990年以来至少对该语言本身进行了两次主要版本修订这一事实很复杂,我确信Turbo-C我当时用的并不完全兼容C89).我不记得我所用的类对二维数组做了什么后果,并将它们传递给函数,期望我需要在不知道编译时的维数的情况下处理数据,这很好.我的头爆炸了.
我正在使用gcc(目前在Ubuntu 14.04的标准存储库中找到的版本),我收集它应该支持C99或C2011标准下的可变长度数组声明,但是我试图用来制作函数的声明识别数组而不必知道编译时的大小是否有关于"冲突类型"的错误.我正在编写警告设置为max,使用一个小的Python程序来节省每次我需要编译时输入一个长命令行(结果命令是gcc -std=c99 -pedantic -Wall -Wextra -o target target.c -lm).以下是原型,来电线和功能定义(代码中充满了警告,导致不良做法,我从书中复制了它;我现在不关心那些,我对学习感兴趣这样做的理智方式,所以我不必使用那些丑陋,令人困惑的方法).
#include <stdio.h>
#include <stdlib.h>
/* ANSI prototypes */
void s2 (int, int, int*);
int main (void);
int main (void)
{
int one[5]={0,1,2,3,4};
int two[3][4] =
{
{0,1,2,3},
{10,11,12,13},
{100,101,102,103}
};
/* try to call s2, it won't work */
printf("\ncalling s2 \n");
s2(1, 5, one);
s2(3, 4, two); /* will be compiler warning */
}
void s2(int rows, int cols, int *x[rows][cols]) …Run Code Online (Sandbox Code Playgroud)