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

问题描述 投票:0回答:3

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

例如,看一下这段代码:

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

编译器是否在编译时将第 2 行“更改”为“char erm = '3'”?

c++ c performance optimization memory-management
3个回答
12
投票

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

但是,是的,现代编译器(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);
}

产生:

...

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

 ...

所以,与

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

现在,它从内部获取值

tesst


8
投票

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

通过最大程度的优化,编译器确实可能会将整个代码替换为

char erm = '3';
。无论如何,GCC -O3 都会这样做。

当然这取决于你如何处理该变量。编译器甚至可能不会分配变量,而只是在变量出现的操作中使用原始数字。


3
投票

取决于编译器版本、使用的优化选项和许多其他因素。如果你想确保 const 变量得到优化,并且它们是编译时常量,你可以在 c++ 中使用类似 constexpr 的东西。与普通 const 变量不同,它保证在编译时进行评估。

编辑:constexpr 可以在编译时或运行时评估。为了保证编译时求值,我们必须在需要常量表达式的地方使用它(例如,作为数组绑定或作为 case 标签),或者使用它来初始化 constexpr。所以在这种情况下

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

会导致编译时间评估。很好读https://isocpp.org/blog/2013/01/when-does-a-constexpr-function-get-evaluated-at-compile-time-stackoverflow

© www.soinside.com 2019 - 2024. All rights reserved.