编译以下C模块
static const int i = 1;
void f (const int *i);
int g (void)
{
f (&i);
return i;
}
在x86_64机器上使用gcc -S -O3
会为函数g
生成以下程序集:
g:
leaq i(%rip), %rdi
subq $8, %rsp
call f@PLT
movl $1, %eax # inlined constant as an immediate
addq $8, %rsp
ret
换句话说,return
语句被编译为将常量$1
移动到返回寄存器%eax
中,这是有道理的,因为i
被声明为常量。
但是,如果我删除const
以便我
static int i = 1;
void f (const int *i);
int g (void)
{
f (&i);
return i;
}
gcc -S -O3
的输出突然变为:
g:
leaq i(%rip), %rdi
subq $8, %rsp
call f@PLT
movl i(%rip), %eax # reload i
addq $8, %rsp
ret
也就是说,在调用f
之后,会从内存中显式加载返回值。
为什么会这样? f
的参数被声明为指向常量int的指针,因此不应允许f
改变i
。此外,f
无法调用通过非const引用修改i
的函数,因为唯一的此函数可能是g
,因为i
被声明为静态。
答案 0 :(得分:4)
将指向const的指针强制转换为指向非const的指针并修改引用的对象并不是未定义的行为,只要引用的对象未声明为const。
6.7.3p6说:“如果尝试通过使用具有非const限定类型的左值来修改使用const限定类型定义的对象,则行为是未定义的。”
答案 1 :(得分:-2)
改变这种情况。身体是众所周知的无需特殊操作。
spring.datasource.platform=h2