使用gcc 9.3编译器输出汇编代码,没有使用优化标志(本回答中的所有内容都是指没有使用优化标志的标准编译):
#include <stdio.h>
int main(void) {
int i = 3;
i++;
printf("%d", i);
return 0;
}
.LC0:
.string "%d"
main:
push rbp
mov rbp, rsp
sub rsp, 16
mov DWORD PTR [rbp-4], 3
add DWORD PTR [rbp-4], 1
mov eax, DWORD PTR [rbp-4]
mov esi, eax
mov edi, OFFSET FLAT:.LC0
mov eax, 0
call printf
mov eax, 0
leave
ret
#include <stdio.h>
int main(void) {
register int i = 3;
i++;
printf("%d", i);
return 0;
}
.LC0:
.string "%d"
main:
push rbp
mov rbp, rsp
push rbx
sub rsp, 8
mov ebx, 3
add ebx, 1
mov esi, ebx
mov edi, OFFSET FLAT:.LC0
mov eax, 0
call printf
add rsp, 8
pop rbx
pop rbp
ret
这会强制使用
ebx
进行计算,这意味着它需要被压入堆栈并在函数结束时恢复,因为它是被调用者保存的。
register
会产生更多的代码行以及1个内存写和1个内存读(尽管实际上,如果计算是在
esi
中完成的话,这可以被优化为0次R / W,这就是使用C ++的
const register
发生的情况)。不使用
register
会导致2次写入和1次读取(尽管在读取时会发生存储器加载转发)。这是因为该值必须直接存在并更新在堆栈上,以便地址(指针)可以读取到正确的值。
register
没有这个要求,也不能被指向。
const
和
register
基本上是
volatile
的相反,使用
volatile
将在文件和块作用域以及块作用域中覆盖const优化。
const register
和
register
将产生相同的输出,因为在C语言的块作用域中,const什么也没做,所以只有
register
优化适用。
在clang中,
register
被忽略,但
const
优化仍然发生。