一个地址两个值?怎么可能!!!
2011-12-30 21:50
169 查看
缘由是这样的:
有个学生写了一个程序,代码如下:
#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了。
这个小程序的调试结果看不出来问题所在,和打印的结果是一样的,但反汇编能瞄出端倪,有兴趣的可以自己看看汇编代码。
总结一下,同一个地址当然不能存放两个不同的值!千万不要被编译器骗了!!!
有个学生写了一个程序,代码如下:
#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了。
这个小程序的调试结果看不出来问题所在,和打印的结果是一样的,但反汇编能瞄出端倪,有兴趣的可以自己看看汇编代码。
总结一下,同一个地址当然不能存放两个不同的值!千万不要被编译器骗了!!!
相关文章推荐
- 触发碰撞事件=大于一个刚体(刚体才可能有碰撞)+两个碰撞器(范围)+istrigle为true
- js实现一个链接打开两个链接地址的方法
- 子网划分的两个例子 怎么算网络号和广播地址
- html中点击radio后的文字相当于选中该单选按钮如何实现?怎么实现两个redio,选中一个,取消另一个?
- 在一个td里面怎么让两个div重叠
- 【算法】输入两个整数序列。其中一个序列表示栈的push顺序,判断另一个序列有没有可能是对应的pop顺序。
- 我的Exchange 2010 启用匿名了。我怎么防止别人任意伪造一个邮件地址发送给我内部的人呢?
- 怎么用两个堆栈实现一个队列?
- 创建一个小球,3秒后变成两个,再过3秒变成4个,再过3秒变成8个,只可以写一个脚本,该怎么编写?
- Solidworks提示字体Arial Unicode MS安装不正确,PDF文件中一个或多个文本字串可能遗失怎么办
- 一个servlet处理多个请求,地址字符串怎么处理呢
- 输入两个整数序列。其中一个序列表示栈的push顺序,判断另一个序列有没有可能是对应的pop顺序
- C# 调试的时候怎么知道两个Reference引用的是同一个对象
- Outlook 中,怎么将一个邮件放进两个(或更多)文件夹里?
- 疑难:有两个公司,一个给的待遇不错,一个感觉有发展潜力,请问大家怎么选择??
- 谷歌面试题:输入是两个整数数组,他们任意两个数的和又可以组成一个数组,求这个和中前k个数怎么做?
- mac登陆窗口 有两个登陆用户,怎么删除一个
- 实践证明:当类想实现两个监听接口的时候,必须把两个都设置成内部类,不可能一个是外部类实现,一个是内部类实现。这样容易捕获错误,出现异常。
- PHP 输入两个整数序列。其中一个序列表示栈的push 顺序, 判断另一个序列有没有可能是对应的pop 顺序
- 有两个瓶子一个瓶承5升水一个瓶子成3升水,那怎么可以成四升水呢