1.const int a = 10;
const int *p1 = &a;
const int *p2 =const_cast<int *>(p1);
*p2 = 2;
*p1, *p2是2了,为什么a 还是10? 但&a, *p1, *p1在输出的地址是相同的啊!
a是const在编译的时候的值已经确定,为常量。用以下代码来说明为什么。
#include <stdio.h>
void f()
{
const int a = 10;
const int *p1 = &a;
int *p2 = const_cast<int *>(p1);
*p2 = 2;
int t = *p1 + *p2;
printf("%d %d", *p1, *p2);
}
反汇编如下
.file "why_const_to_nonconst.cpp"
.section .rdata,"dr"
LC0:
.ascii "%d %d\0"
.text
.globl __Z1fv
.def __Z1fv; .scl 2; .type 32; .endef
__Z1fv:
LFB8:
pushl %ebp
LCFI0:
movl %esp, %ebp
LCFI1:
subl $40, %esp
LCFI2:
movl $1, -24(%ebp) ; const int a = 1;
leal -24(%ebp), %eax ;
movl %eax, -12(%ebp) ; const int *p1 = &a;
movl -12(%ebp), %eax ;
movl %eax, -16(%ebp) ; int *p2 = const_cast<int *>(p1);
movl -16(%ebp), %eax ;
movl $2, (%eax) ; *p2 = 2;
movl -12(%ebp), %eax ;
movl (%eax), %edx ;get *p1
movl -16(%ebp), %eax ;
movl (%eax), %eax ;get *p2
leal (%edx,%eax), %eax ;
movl %eax, -20(%ebp) ; int t = *p1 + *p2;
;; 以下是printf的传参数
movl -16(%ebp), %eax ;
movl (%eax), %edx ;get *p1
movl -12(%ebp), %eax ;
movl (%eax), %eax ;get *p2
movl %edx, 8(%esp) ;8(%esp) = *p1
movl %eax, 4(%esp) ;4(%esp) = *p2
movl $LC0, (%esp)
call _printf
leave
LCFI3:
ret
LFE8:
.def _printf; .scl 2; .type 32; .endef
显然,p1,p1的值是相同的,即指向同一个位置。执行*p2 = 2, *p1,*p2就是2。
修改原来的代码如下,与上述代码进行对比。
#include <stdio.h>
void f()
{
const int a = 10;
const int *p1 = &a;
int *p2 = const_cast<int *>(p1);
*p2 = 2;
int t = *p1 + *p2 + a;//修改的代码
printf("%d %d", *p1, *p2);
}
.file "why_const_to_nonconst.cpp"
.section .rdata,"dr"
LC0:
.ascii "%d %d\0"
.text
.globl __Z1fv
.def __Z1fv; .scl 2; .type 32; .endef
__Z1fv:
LFB8:
pushl %ebp
LCFI0:
movl %esp, %ebp
LCFI1:
subl $40, %esp
LCFI2:
movl $10, -24(%ebp)
leal -24(%ebp), %eax
movl %eax, -12(%ebp)
movl -12(%ebp), %eax
movl %eax, -16(%ebp)
movl -16(%ebp), %eax
movl $2, (%eax)
movl -12(%ebp), %eax
movl (%eax), %edx
movl -16(%ebp), %eax
movl (%eax), %eax
leal (%edx,%eax), %eax ; tmp = *p1 + *p2
addl $10, %eax ; result = tmp + a
movl %eax, -20(%ebp) ; int t = result
movl -16(%ebp), %eax
movl (%eax), %edx
movl -12(%ebp), %eax
movl (%eax), %eax
movl %edx, 8(%esp)
movl %eax, 4(%esp)
movl $LC0, (%esp)
call _printf
leave
LCFI3:
ret
LFE8:
.def _printf; .scl 2; .type 32; .endef
addl $10, %eax ; result = tmp + a
可以看到a被直接用常量10代替, 由此可以看到编译器在编译时将const常量替换成“常量”。
&a虽然是a的地址,如果&a这个盒子所存储的东西被修改了, 与a没有关系。因为在编译的时候a被替换成常量了,如上面的10。
由以上可以看到a在编译时已经被替换成真正的常量,&a位置和*p1和*p2是指向相同的地址的。