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

Mån*_*son 5 c c++ optimization performance memory-management

当涉及到C和C++语言时,编译器是否优化对常量变量的引用,以便程序自动知道所引用的值,而不必查看常量变量的内存位置?说到数组,是否取决于在编译时指向数组的索引值是否为常量?

例如,看看这段代码:

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

编译器编译器是否将第2行"更改"为"char erm ='3'"?

Mat*_*son 10

我个人希望发布的代码变成"无",因为这两个变量实际上都没有使用,因此可以删除.

但是,现代编译器(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("%d\n", erm);
}
Run Code Online (Sandbox Code Playgroud)

生产:

...

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

 ...
Run Code Online (Sandbox Code Playgroud)

所以,同样如此printf("%d\n", '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("%d\n", 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
Run Code Online (Sandbox Code Playgroud)

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


Lun*_*din 7

它主要取决于优化级别和您使用的编译器.

通过最大程度的优化,编译器确实可能只是用你的整个代码替换char erm = '3';.无论如何,GCC -O3都是这样做的.

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