【问题标题】:run-time const to define array size [duplicate]运行时常量来定义数组大小
【发布时间】:2012-03-21 20:56:37
【问题描述】:

可能重复:
C/C++: Array size at run time w/o dynamic allocation is allowed?

在下面的清单中,buf 的大小显然是由运行时常量j 决定的。 编译器如何生成代码在栈上分配存储空间(编译时不知道j的值)?

#include<iostream>
#include<cstdlib>

using namespace std;

int main(){
  srandom(time(NULL));    
  int i = random();
  cout<< "random number: "<<i<<endl;
  if(i%2==0)
    i=2;
  else
    i=1;
  const int j=i;
  char buf[j];
  std::cout<<"size of buf array: "<<sizeof(buf)<<endl;
  return 0;   
}

【问题讨论】:

  • 让我猜猜……你是用 g++ 编译的吗?这是允许 C99 的 VLA 的非标准扩展。 C++ 不允许它们。使用 -pedantic 和/或 -Wall 编译
  • objdump -d -S my_file 如果您想查看编译器为该行生成的代码。此外,-pedantic(假设 g++):warning: ISO C++ forbids variable length array ‘buf’
  • 没错!收到了-pedantic 的警告,但没有收到-Wall 的警告。

标签: c++


【解决方案1】:

我假设您使用的是 gcc,因此是 VLA 扩展。这不是标准 C++,它是从 C++0x (1x) 中删除的。

原因是它并不是真的那么有用,而且由于更强大的类型系统,C++ 实现将比 C 中的实现复杂得多。

真的,如果您正在堆栈分配未知大小的数组,那么您同时在编写很可能会破坏堆栈的危险代码。如果您知道大小,那么这不是问题,否则只需动态分配它。当然有完全有效的用例,这是一个“很高兴拥有”的功能,但他们最终决定反对它。

Here is a good run down on the subject.

【讨论】:

  • 说它是从 C++11 中删除的,非常具有误导性。它从来都不是标准 C++ 的一部分。它被提议在 C++11 草案过程中包含,但被拒绝。而那个新闻组线程完全错过了这一点,IMO,因为它完全忽略了 POD 数组(C VLA 是)和非平凡对象数组之间的行为差​​异。
【解决方案2】:

符合标准的 C++ 编译器不会接受您的代码。尽管是constj 并不是一个常量表达式。

gcc 在 C++ 代码中接受这个作为扩展(根据语言标准,它只允许在 C99 代码中)。基本上,它在堆栈上为buf 分配空间。它(通常)通过从当前堆栈指针中减去一些数量来做到这一点。从生成的代码的角度来看,在典型机器上处理非常量是非常简单的。

【讨论】:

  • @BenVoigt:你当然知道,但我们说的是 C++,C99 肯定不适用于它。
  • @EdS:当然,但是 Jerry 提到了“gcc”,两者兼而有之。而gcc 命令是 gcc 的 C 编译器部分,这进一步混淆了问题。
  • 我是用 g++ 命令编译的。我想那么 gcc 的 C 部分不应该在这里应用吗?
  • @amirmonshi:无论哪种方式,它基本上都是相同的编译器,尽管它以两种不同的模式运行。理论上,在 C++ 模式下(如果它完全遵循标准)它不会接受这一点,但他们显然认为它足够有用,可以在 C++ 模式和 C 模式下启用它。
【解决方案3】:

编译器只需增加堆栈大小并将 buf 变量指向堆栈上新创建的空间。没有理由不能在运行时动态地完成给定大小。 (尽管从编程的角度来看这样做可能并不明智。)

【讨论】:

  • 没有任何理由,除了 C++ 要求每个变量都具有在编译时已知的常量大小(正式的常量整数表达式)。
  • @BenVoigt 是的,但问题是“编译器如何做到这一点?”答案很简单。所有其他讨论都是重要信息,但不一定回答编译器如何做到这一点的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-04
  • 1970-01-01
  • 2010-12-08
  • 2017-05-23
  • 2015-11-19
  • 1970-01-01
相关资源
最近更新 更多