编译器是否优化了对常数变量的引用
Does the compiler optimize references to constant variables?
当涉及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
- C++Boost Asio Pool线程,带有lambda函数和传递引用变量
- 多个"常量引用"变量可以共享同一个内存吗?
- 如果非动态变量被指针引用,何时超出范围?
- 在 c++ 中将变量作为结构构造函数中的引用传递
- 在 gtest 中初始化堆栈上的引用变量的隔离错误
- 为什么C++可以使用未初始化的成员变量(引用或指针 *NOT 值复制*)来初始化其父类的成员变量
- 地址运算符是否返回变量引用的对象的地址
- 未在另一个函数中设置变量引用的问题
- 英特尔样式内联程序集和 AT&T 样式中的变量引用,C++
- 将成员变量引用为类成员
- 从静态变量引用非静态变量会使非静态变量先于静态变量进行析构函数
- 何时解析 C++11 lambda 表达式中的变量引用
- 堆栈/堆变量的变量/引用名称或类型存储在内存中的位置
- C++强制对变量引用进行编译优化,使之成为直接的
- Boost变量引用和相等比较
- 使复制的成员引用变量引用副本的成员,而不是原始成员的成员
- 为什么要在Java中生成变量引用数组
- 捕获和调试对移动lambda内部局部变量引用的无效使用
- 在变量初始化后更改变量引用
- 从'C'程序中提取变量定义和变量引用