当涉及到C和 C++ 时,编译器是否优化了对常量变量的引用,以便程序自动知道引用了什么值,而不必查看常量变量的内存位置?当涉及到数组时,它是否取决于数组中要指向的索引值在编译时是否是常量?例如,看看这段代码:
int main(void) { 1: char tesst[3] = {'1', '3', '7'}; 2: char erm = tesst[1]; }
编译器是否在编译时将第2行“更改”为“char = '3'"?
qacovj5a1#
我个人希望发布的代码变成“无”,因为这两个变量实际上都没有使用,因此可以删除。但是,是的,(gcc,clang,msvc等)应该能够用它的常量值替换对替代项的引用[只要编译器可以合理地确定tesst的内容没有被改变-如果你将tesst传递到一个函数中,即使它是一个const引用,编译器实际上并不知道函数没有改变它,它会假设它改变了,并加载值。使用clang -O1 opts.c -S编译:
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给出了完全相同的代码,除了一些符号名称略有不同)为了说明“如果你调用一个函数,它可能不会这样做”:
printf("%d\n", '3');
cout
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内部获取值。
up9lanfz2#
这主要取决于优化的级别和您使用的编译器。在最大限度优化的情况下,编译器很可能会用char erm = '3';替换整个代码。GCC -O3无论如何都会这样做。当然,这取决于你如何处理这个变量。编译器甚至可能不分配变量,而只是在变量出现的操作中使用原始数字。
char erm = '3';
9udxz4iz3#
取决于编译器版本、使用的优化选项和许多其他因素。如果你想确保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
3条答案
按热度按时间qacovj5a1#
我个人希望发布的代码变成“无”,因为这两个变量实际上都没有使用,因此可以删除。
但是,是的,(gcc,clang,msvc等)应该能够用它的常量值替换对替代项的引用[只要编译器可以合理地确定
tesst
的内容没有被改变-如果你将tesst
传递到一个函数中,即使它是一个const
引用,编译器实际上并不知道函数没有改变它,它会假设它改变了,并加载值。使用
clang -O1 opts.c -S
编译:生产:
与
printf("%d\n", '3');
相同。[我使用C而不是C++,因为如果我使用
cout
,它将是大约50行汇编程序,因为所有内容都是内联的]我希望gcc和msvc也能进行类似的优化(测试过的
gcc -O1 -S
给出了完全相同的代码,除了一些符号名称略有不同)为了说明“如果你调用一个函数,它可能不会这样做”:
现在,它从
tesst
内部获取值。up9lanfz2#
这主要取决于优化的级别和您使用的编译器。
在最大限度优化的情况下,编译器很可能会用
char erm = '3';
替换整个代码。GCC -O3无论如何都会这样做。当然,这取决于你如何处理这个变量。编译器甚至可能不分配变量,而只是在变量出现的操作中使用原始数字。
9udxz4iz3#
取决于编译器版本、使用的优化选项和许多其他因素。如果你想确保const变量是优化的,如果它们是编译时常量,你可以在c++中使用类似constexpr的东西。与普通的const变量不同,它保证在编译时被计算。
编辑:constexpr可以在编译时或运行时计算。为了保证编译时求值,我们必须在需要常量表达式的地方使用它(例如,作为数组边界或作为case标签),或者使用它来初始化constexpr。所以在这种情况下
会导致编译时的评估。阅读https://isocpp.org/blog/2013/01/when-does-a-constexpr-function-get-evaluated-at-compile-time-stackoverflow