编译器是否优化了对常数变量的引用

Does the compiler optimize references to constant variables?

本文关键字:变量 引用 常数 是否 优化 编译器      更新时间:2023-10-16

当涉及C和C 语言时,编译器会优化对常数变量的引用,以便程序自动知道正在引用哪些值,而不必窥视内存的内存恒定变量的位置?当涉及数组时,是否取决于在编译时间中指向数组中指向的索引值是否是常数?

例如,查看此代码:

int main(void) {
    1:  char tesst[3] = {'1', '3', '7'};
    2:  char erm = tesst[1];
}

编译器在编译时"更改"第2行对" char erm ='3'"?

我个人期望发布的代码将变成" Nothing",因为实际上都没有使用变量,因此可以删除。

但是,是的,现代编译器(GCC,Clang,MSVC等)应该能够用其恒定值替换对替代方案的引用[只要编译器可以合理地确定tesst的内容不是更改 - 如果将tesst传递到函数中,即使其作为const参考,并且编译器实际上并不知道该函数不会更改该函数,它将假定它可以并加载值]。

>

使用clang -O1 opts.c -S

对此进行编译
#include <stdio.h>
int main()
{
    char tesst[3] = {'1', '3', '7'};
    char erm = tesst[1];
    printf("%dn", erm);
}

生产:

...
main:
    pushq   %rax
.Ltmp0:
    movl    $.L.str, %edi
    movl    $51, %esi
    xorl    %eax, %eax
    callq   printf
    xorl    %eax, %eax
    popq    %rcx
    retq
 ...

所以,与printf("%dn", '3');相同。

[我使用C 而不是C ,因为如果我使用cout,那将是大约50行汇编器,因为一切都被夹住了]

我希望GCC和MSVC能够进行类似的优化(测试的gcc -O1 -S,它给出了完全相同的代码,除了某些符号名称略有不同)

并说明"如果您调用函数,则可能不会这样做":

#include <stdio.h>
extern void blah(const char* x);
int main()
{
    char tesst[3] = {'1', '3', '7'};
    blah(tesst);
    char erm = tesst[1];
    printf("%dn", erm);
}

main:                                   # @main
    pushq   %rax
    movb    $55, 6(%rsp)
    movw    $13105, 4(%rsp)         # imm = 0x3331
    leaq    4(%rsp), %rdi
    callq   blah
    movsbl  5(%rsp), %esi
    movl    $.L.str, %edi
    xorl    %eax, %eax
    callq   printf
    xorl    %eax, %eax
    popq    %rcx
    retq

现在,它从tesst内部获取值。

它主要取决于优化级别以及您正在使用的编译器。

有了最大的优化,编译器确实可能只需用char erm = '3';替换您的整个代码。gcc -o3无论如何都这样做。

,但是当然,这取决于您对该变量的处理。编译器甚至可能不会分配变量,而只使用发生变量发生的操作中的原始数字。

取决于编译器版本,所使用的优化选项以及许多其他内容。如果要确保优化const变量,并且如果它们是编译时间常数,则可以在C 中使用 constexpr 之类的内容。与正常的const变量不同,可以保证在编译时间进行评估。

编辑:可以在编译时间或运行时评估ConstexPR。为了保证编译时间评估,我们必须在需要恒定表达式(例如,作为数组绑定或作为情况标签)或使用它来初始化constexpr的情况下使用它。因此,在这种情况下

constexpr char tesst[3] = {'1','3','7'};
constexpr char erm = tesst[1];

将导致编译时间评估。在https://isocpp.org/blog/2013/01/when-does-a-constexpr-function-function-get-evalec--at-at-compile time-stackoverflow