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是指向相同的地址的。