相关疑难解决方法(0)

可以使用const变量来声明C中数组的大小吗?

为什么以下代码会抛出错误?

const int a = 5;
int b[a]={1,2,3,4,5};
Run Code Online (Sandbox Code Playgroud)

而且当我尝试编译没有"const"关键字的上述代码时,我得到了同样的错误:

int a = 5; 
int b[a]={1,2,3,4,5};
Run Code Online (Sandbox Code Playgroud)

为什么会这样?我在这里做的错误是什么?

还有另一个问题:什么时候常量被代码中的实际值替换,即如果我声明一个变量说:const int x = 5; 我知道在RAM中没有为变量x分配内存,但是ROM中的常量变量区域保持值5,并且x在代码中出现x的地方简单地替换为值5.但这什么时候发生的?编译时间?启动时间?预处理时间?

PS:我说的是嵌入式C(在微控制器上运行等),而不是在桌面上运行的C. 因此嵌入式系统必然会有一个ROM(Flash,EEPROM ......).那会发生什么?

c arrays const

37
推荐指数
3
解决办法
3万
查看次数

GCC如何实现可变长度数组?

GCC如何实现可变长度数组(VLA)?这些数组是否基本上指向动态分配的存储,例如alloca返回的存储?

我能想到的另一个选择是,这样的数组被分配为函数中的最后一个变量,因此在编译时可以知道变量的偏移量.但是,在编译期间,第二个VLA的偏移量将再次不知道.

c arrays gcc

20
推荐指数
2
解决办法
5920
查看次数

与malloc/free相比,使用C99 VLA是个好主意吗?

使用C99 VLA是个好主意吗?与malloc/free相比,何时使用VLA是否合适?(因为VLA可能会爆炸堆叠?)

c c99

19
推荐指数
1
解决办法
6998
查看次数

C++中的可变长度数组开销?

看看这个问题:为什么C/C++编译器在编译时需要知道数组的大小?它来到我身边,编译器实现者应该有一些时间来弄清楚它(它是C99标准的一部分,那是10年前)并提供有效的实现.

然而,(从答案中)似乎仍然被认为是昂贵的.

这让我感到惊讶.

当然,我理解静态偏移在性能方面比动态偏移要好得多,并且不像一个建议我实际上不会让编译器执行数组的堆分配,因为这可能会花费更多[这没有被测量;)]

但我仍然对所谓的成本感到惊讶:

  • 如果一个函数中没有VLA,那么就我所见,不会有任何代价.
  • 如果有一个单独的VLA,那么可以在所有变量之前或之后放置它,因此获得大部分堆栈帧的静态偏移量(或者在我看来,但是我对堆栈管理并不精通) )

当然,问题出现在多个VLA上,我想知道是否有专用的VLA堆栈可行.这意味着VLA将由计数和指针(因此已知大小)表示,并且在辅助堆栈中采用的实际内存仅用于此目的(因此也是堆栈).

[改述]

如何在gcc/VC++中实现VLA?

成本真的令人印象深刻吗?

[结束改写]

在我看来,它只能比使用a vector,即使现有的实现更好,因为你不会产生动态分配的代价(以不可调整大小为代价).

编辑:

有部分反应在这里,但是比较沃拉斯传统阵列似乎不公平.如果我们事先知道尺寸,那么我们就不需要VLA了.在同一个问题中,AndreyT给出了一些关于实现的指示,但它并不像我想的那样精确.

c++ variable-length-array

13
推荐指数
1
解决办法
1078
查看次数

无论如何,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
查看次数

是否需要从堆栈中分配C可变长度数组?

从我们的嵌入式系统代码中删除对malloc和calloc的所有调用后,我惊讶地发现malloc仍然被链接.调用图指向一个没有显式*alloc调用的函数,并且没有调用任何可能分配的库函数,比如strdup.
我必须查看生成的程序集才能意识到它是由于包含VLA的内联函数.

我认为VLA必须是堆栈分配的.这个编译器坏了吗?

c heap-memory variable-length-array

6
推荐指数
2
解决办法
1064
查看次数

标签 统计

c ×5

variable-length-array ×3

arrays ×2

c++ ×1

c99 ×1

const ×1

gcc ×1

heap-memory ×1