我正在编写包含大量 const 变量(主要是整数和枚举)的代码,我想知道我可以声明的变量数量是否有最大限制?我的想法是,这些 const 变量分配在堆栈上,这意味着我可以声明大约 1MB/4bytes = 250000 个变量(这足够了),假设堆栈大小为 1MB。我说得对吗?
我的意思的一个简单例子:
测试.cpp:
const unsigned int VECTOR_ID = 4;
const unsigned int MATRIX_ID = 3;
int main()
{
std::cout << VECTOR_ID << " : " << MATRIX_ID << std::endl;
return 0;
}
注意,编译时已知的常量可能不对应于任何对象;当您在启用优化的情况下进行编译时,常量将作为立即值直接编译到机器指令中。这里是一个简单的示例。这意味着常量变量的数量没有限制。这也意味着根本不使用的常量可能会完全消失。 (并且如果以任何不平凡的方式使用它们,代码的大小将超过数据的大小。)
即使你的常量变量确实变成了对象,例如因为它们的地址被占用,它们将被“编译到您的程序中”并成为可执行文件的一部分。
程序的大小及其段的大小受到可执行文件格式、系统资源以及可能的构建工具的限制。 Intel 页面似乎表明,即使在 64 位架构上,静态数据(全局常量可能最终出现的地方)在 Windows 下也限制为 2 GB(这仍然比您的用例大三个数量级):
请注意,静态数据和堆栈数据的限制在 32 位和 64 位变体中是相同的。这是由于 Windows 可移植可执行文件 (PE) 文件类型的格式造成的,该文件类型用于描述链接器所布置的 EXE 和 DLL。它具有用于图像部分偏移和长度的 32 位字段,并且未针对 Windows 的 64 位变体进行扩展。与 32 位 Windows 一样,静态数据和堆栈共享相同的前 2GB 地址空间。
快速搜索似乎表明现代 Linux 中不存在此限制。
独立于任何二进制限制,构建工具(编译器和链接器)可能有更多限制。即使稍后的优化器阶段消除了所有常量,仍然需要解析它们的定义。范围或翻译单元中的名称数量可能存在限制。
我刚刚创建了一个有关 C++ 程序的数据点,其中包含 200 万个外部变量和 200 万个局部变量:
-Wl,--stack,20000000
来显式设置堆栈大小(这样它就变成了 gcc -O0 -Wl,--stack,20000000 -o many2 many2.cpp
;20000000 是一个安全的猜测)。如果没有该设置,则会生成可执行文件,但在运行时崩溃。源代码长 101,555,599 字节,可执行文件只有 64,028,280 字节。在我相当普通的电脑上,编译需要一分钟多一点的时间。cl /O0 many2.cpp
。自我注意:不要指定
-Wall
,因为每个未使用的变量都会在终端上生成警告。在 msys 下的 mintty 上打印数百万行比我愿意等待的时间要长(推断,一定是几个小时)。