Are those constant arrays allocates space in memory or compilers are smart enough and decays this into something literal?
I will just provide an example here:
const int array[] = {
1, 2, 3, 4, 5
};
Well, I just wanted to know nothing else.
简短的回答是:这取决于。
长答案是:
如果你编译这个:
const int array[] = {
1, 2, 3, 4, 5
};
int
main()
{
return array[0];
}
你最终在 x86/Linux(简化)上得到了这个:
.globl main
main:
movl $1, %eax
ret
所以是的,它不会存储在任何地方,而是被视为在编译时评估的常量。
但是,如果您这样使用它:
const int array[] = {
1, 2, 3, 4, 5
};
int
main()
{
return (long)array;
}
它成为了:
.globl main
main:
leal _ZL5array(%rip), %eax
ret
.section .rodata
.align 16
_ZL5array:
.long 1
.long 2
.long 3
.long 4
.long 5
它在 rodata 部分结束,因为你告诉编译器你实际上需要它作为一个数组。
Qt 背后的专家之一 Olivier Goffart有一篇关于 C++ 中数据初始化的优秀博客文章。
优化器实际上是非常聪明的生物。例如,这段代码:
const int array[] = {1, 2, 3, 4, 5};
void show(int i)
{
printf("%d\n", i);
}
int main(int argc, char * argv[])
{
show(array[0]);
}
很可能最终会变成:
void show()
{
printf("%d\n", 1);
}
int main(int argc, char * argv[])
{
show();
}
我猜,那个优化器会注意到,那个节目可能很容易被内联,所以代码可能会被进一步优化:
int main(int argc, char * argv[])
{
printf("%d\n", 1);
}
从理论上讲,这完全取决于实施。C++ 标准定义了你得到的行为——你如何得到它留给魔法。
在实践中,我希望每个编译器(平台支持它)在编译时将该数组放在一个 const 段中,并直接从那里使用它。
随着优化器的进行,在前面创建的“const”对象的状态是固定的(标准使得通过任何方式更改它们的行为都是未定义的),并且数据流分析器会考虑到这一点。从已知位置从数组中读取值可以并且通常由数字代替。
此外,使用顶级 const 的 IIRC 默认情况下使对象静态,因此除非您使用“extern”,否则它将在翻译单元中是私有的。如果代码中没有任何东西真的需要它(获取是按值内联的),它根本不会被发出。
大多数编译器都可以选择发出汇编/机器代码输出,以便您可以检查它对特定实现的作用,或者您可以使用目标文件转储器来查看数组的存在。
我相信它们可以很容易地优化,如果它们是static
. 用一些技巧(比如const_cast
ing 它)改变它们的值是未定义的行为,所以编译器不会关心。无论如何 - 你可以检查。gcc -O2 -S temp.c
.
如果数组是全局的而不是全局static
的,编译器应该保留它以防其他编译单元需要它。除非您进行整个程序优化。