一个地址两个值?怎么可能!!!

缘由是这样的:

      有个学生写了一个程序,代码如下:

#include <stdio.h>
int main(void)
{
    const int a = 10;
    *(int *)&a = 20;
    if ( a == 20)
        printf("a = 20\n");

    printf("%d, %X\n", a, &a);;
    printf("%d, %X\n",*(int *)&a,(int *)&a);
    return 1;
}
程序的输出结果相信大家都知道,我也贴出来吧
10, 31F73C
20, 31F73C
    看到这个结果,这个学生就有点懵了,他问:
    “同一个地址,怎么会有两个值呢?”
    当时,我看的时候,初以为他是用C语言编译器编译的,我就问他这怎么会通过编译阶段呢?(注:学院教的是MTK开发,开发语言用的是C语言,所以先入为主了。)
    后来一看文件类型,哦,原来是.cpp文件。Visual C++ 6.0默认新建源文件的格式是cpp文件,编译用的当然是C++的编译器;如果文件名写明了.c(比如test.c),那么编译的时候就会使用C语言的编译器进行编译。

    这个小程序里面的关键之处就是const,如果把它去掉,则每个会C的都能懂。关于const的用法,网上有很多很深入的探索 ,我这里就不再详细谈了,请参考:
1. http://www.vckbase.com/document/viewdoc/?id=412  ————————const使用详解
2. http://www.cnblogs.com/yc_sunniwell/archive/2010/07/14/1777416.html ——————C/C++中const关键字详解
    只说一点:在C语言中const修饰成“只读变量” ;在C++中修饰成“常量”。

    常量一般来说是不可以改变的,也就是不可以给它赋值。但程序里没有这么做,而是直接把a的地址取出来,然后根据地址在内存里直接放入20,这是没有问题的。当我说到这里的时候,这个同学发问了:“你说a的值改变了?那为什么 if 判断为假呢?”。我接着跟他说,a不是一个值,它只是内存里某个地址的代号。至于

if ( a == 20)确实不会为真,因为10不可能等于20。在VC编译器编译代码的时候,它会有一个“源代码优化”的阶段,当它检测到常量a的时候,会把后面的a
都替换成10,所以if语句判断为假,从第二条打印语句也可以看出来。最后一条打印语句的意思是,取a所代表的内存地址中的值,所以肯定是20,而不是10了。
    这个小程序的调试结果看不出来问题所在,和打印的结果是一样的,但反汇编能瞄出端倪,有兴趣的可以自己看看汇编代码。
    总结一下,同一个地址当然不能存放两个不同的值!千万不要被编译器骗了!!!

 

 

posted @ 2011-12-30 21:50  ZhangW  阅读(741)  评论(3编辑  收藏  举报