这个问题应该这么看。首先通过指针去掉变量的const属性的行为是未定义的,讨论起来其实没什么意义。然后我们分析一下这个结果是怎么来的。
下面是一段GCC编译过后的代码:
movl $3, -4(%ebp)
leal -4(%ebp), %eax
movl $3, %edx
movl %eax, 16(%esp)
movl %eax, 12(%esp)
xorl %eax, %eax
movl %edx, 8(%esp)
movl %eax, 4(%esp)
movl $LC0, (%esp)
call _printf
可以明显看出,因为a是常数,因此在使用a的时候,编译器直接使用了a的值,而不是从a的内存地址读取a的值。
但在VC编译的时候,因为过度优化,编译器直接写0,3两个数字进去了。所以我给a加了一个属性,如下:
volatile const int a=3;
强迫编译器,每次都要读a的值。于是在VC下,第一个程序的输出变成了a=3,p=3
但是在GCC下无效。观察源代码发现,编译器对a的值的改变在printf语句的后面(ft……)可能是编译器认为既然使用a的值的时候,a的值并没有改变。所以两条语句的顺序可以随意改变吧……反正这么写
volatile const int a=0;
int *p=(int*)&a;
*p=3;
printf("a=%d,*p=%d\n",a,*p);
printf("a=%d",a);
输出的结果是a=0,*p=3,a=3………………这个么,这个应该不算编译器Bug,因为编译器不必为这种行为负责:改变常量的行为本身就是未定义的……
第二个问题很简单。p的确是指向常量的指针。但是a不是常量啊,a的值是可以改变的。所以a改变以后,p的值也跟着改变咯……