Mar*_*arc 5 c assembly gcc compiler-optimization
编译以下C模块
static const int i = 1;
void f (const int *i);
int g (void)
{
f (&i);
return i;
}
Run Code Online (Sandbox Code Playgroud)
gcc -S -O3在x86_64机器上使用会为函数生成以下程序集g:
g:
leaq i(%rip), %rdi
subq $8, %rsp
call f@PLT
movl $1, %eax # inlined constant as an immediate
addq $8, %rsp
ret
Run Code Online (Sandbox Code Playgroud)
换句话说,return语句被编译为将常量移动$1到返回寄存器中%eax,这是有道理的,因为它i被声明为常量.
但是,如果我删除它,const那么我有
static int i = 1;
void f (const int *i);
int g (void)
{
f (&i);
return i;
}
Run Code Online (Sandbox Code Playgroud)
输出gcc -S -O3突然变成:
g:
leaq i(%rip), %rdi
subq $8, %rsp
call f@PLT
movl i(%rip), %eax # reload i
addq $8, %rsp
ret
Run Code Online (Sandbox Code Playgroud)
也就是说,在调用之后,从内存中显式加载返回值f.
为什么会这样?f声明的参数是一个指向常量int的指针,所以f不应该允许改变i.此外,f不能调用修改函数i通过非const引用,因为只有这样的功能可能是g因为i被声明为静态的.
只要引用的对象未声明为 const,将指向 const 的指针转换为指向非 const 的指针并修改引用的对象就不是未定义行为。
6.7.3p6 说:“如果尝试通过使用非 const 限定类型的左值来修改用 const 限定类型定义的对象,则行为是未定义的。”