Benjamin

静以修身,俭以养德,非澹薄无以明志,非宁静无以致远。
随笔 - 397, 文章 - 0, 评论 - 196, 引用 - 0
数据加载中……

两个变量,一个地址

偶然在CSDN的论坛上看到这样的题目,代码如下:
 const int a=3;
    int *p=(int*)&a; 
    *p=100; 
    printf("*p =%d,a = %d\n",*p,a);
printf("p = %p,a = %p\n",p,&a);
程序中p和a的地址一样,可值不一样,容易让人产生错觉。有人说这样做改变了常量a的值,调试跟踪中发现a的值是100,可输出的却是3;还有人认为是常量折叠的缘故。其实这两种说法都是错误的,没抓住问题的本质。在这个程序中,通过int *p=(int*)&a;这个语句,常量a和指针p的地址是一样的,但是由于它们所属的内存区的不同,在栈区我们看到*p值是100,常量区的值是3.
在C++中,常量确实不分配内存,但是当对常量取地址时就已经分配了空间,常量是不可以改变的,但我们要记住的是:常量和常量的地址是两个概念,常量不可以改变,但是常量的地址可以改变,所以说,改变了常量a的值,说法是不正确的;至于在调试中,发现a的值是100(VC编译器的调试模式下的观察窗口下,用鼠标点到a的地址处),可输出的是3,那是因为,常量a和变量p是一个地址,但是却分属不同的内存区域,a是常量区,p是栈区,我们观察的地址在栈中,所以看到的值是100(其实是存储在指针p指向的地址中的值100),可输出a的值3,a的值并没变;这里和常量折叠的关系不大,至少不是它的实质,如果把const去掉值就一样了。
值得注意是:这样的代码容易让人产生错觉,如果再有内存分配的话,很容易出问题,并不提倡这样的代码。一直一来认为,C++很大,注重的是细节,这里再次验证了这一点。

posted on 2009-01-11 00:40 Benjamin 阅读(789) 评论(3)  编辑 收藏 引用 所属分类: C/C++

评论

# re: 两个变量,一个地址  回复  更多评论   

是因为被优化了
2009-01-11 01:21 | 陈梓瀚(vczh)

# re: 两个变量,一个地址  回复  更多评论   

调试跟踪一下
2009-01-11 10:31 | Herb

# re: 两个变量,一个地址  回复  更多评论   

我对一楼说的补充下,其实很简单,对于const对象,编译器是会做优化的,像内建类型的数据,比如int,float这些,编译器会直接优化成立即数,举个例子,现在有这么一条语句:
const int const_value = 1113;
int value = const_value;
vc的汇编窗口中对应的汇编代码是这样的:
004113AE mov dword ptr [const_value],9
004113B5 mov dword ptr [value],9
可以看出来,虽然优化了,但是,优化的并不是const_value本身,const_value依然是分配了内存的,真正被优化的是对const_value的取值操作,可以从004113B5这条语句看出来,对const_value的取值被直接化成了一个立即数。
所以这篇文章中的问题我们能清楚的解释了,原因是:
对于const的语言内建类型数据,其取值操作会被优化成立即数访问,而涉及到内存读写的操作,则和其他的变量操作是一样的。
2009-01-11 16:47 | dophi

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理