c++编译器如何处理const数组

How const arrays are treated by C++ compilers

本文关键字:处理 const 数组 编译器 何处理 c++      更新时间:2023-10-16

这些常量数组是否在内存中分配空间或编译器是否足够聪明并将其分解为文字?

我在这里只提供一个例子:

const int array[] = {
    1, 2, 3, 4, 5
};

我只是想知道别的。

简短的回答是:看情况。

长答案是:

如果你编译这个:

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

它在section rodata中结束,因为你告诉编译器你实际上需要它作为一个数组。

有一篇关于c++中数据初始化的优秀博文,作者是Qt背后的专家之一Olivier Goffart。

我相信他们可以很容易地优化,如果他们是static。用一些技巧改变它们的值(比如const_cast)是未定义的行为,所以编译器不会在意。不管怎样,你可以检查一下。gcc -O2 -S temp.c .

如果数组是全局的而不是static,编译器应该保留它,以防其他编译单元需要它。除非你做了整个程序的优化

优化器实际上是非常聪明的生物。例如,下面的代码:

const int array[] = {1, 2, 3, 4, 5};
void show(int i)
{
    printf("%dn", i);
}
int main(int argc, char * argv[])
{
    show(array[0]);
}

很可能以

结尾
void show()
{
    printf("%dn", 1);
}
int main(int argc, char * argv[])
{
    show();
}

我猜,优化器会注意到,这个show可能很容易内联,所以代码可能会进一步优化:

int main(int argc, char * argv[])
{
    printf("%dn", 1);
}

理论上这完全取决于实现。c++标准定义了你得到的行为——如何得到它是不可思议的。

在实践中,我希望每个编译器(平台支持它的地方)在编译时将该数组放在const段中,并从那里直接使用它。

随着优化器的发展,前面创建的"const"对象的状态是固定的(标准规定以任何方式改变它们都是未定义的行为),数据流分析器会考虑到这一点。从已知位置的数组中读取值可以,通常用数字代替。

另外,IIRC使用顶级const使对象默认为静态,所以除非你使用'extern',否则它在翻译单元中将是私有的。如果代码中没有真正需要它(读取是按值内联的),则根本不会发出它。

大多数编译器都有发出汇编/机器代码输出的选项,这样你就可以检查它对特定实现做了什么,或者你可以使用对象文件转储器来查看数组的存在。