为什么输出结果不对??

NesTa_xP 2008-10-26 11:07:21
const int a=10;
int* p=const_cast<int*>(&a);
*p=1;
cout<<a;

为什么输出结果不是1 而是10呢??
const_cast不是把变量a的const特性消除了吗?而p指向a的地址,并切给*p赋值1,但是a的值为什么没变呢?
...全文
117 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
NesTa_xP 2008-10-27
  • 打赏
  • 举报
回复
#include<iostream>
using namespace std;
int main()
{
const double cd[5]={1,2,3,4,5};
volatile double vd[5]={1,2,3,4,5};
double* pc;
double* pv;
for(int i=0;i<5;i++)
{
pc=const_cast<double*>(cd+i);
pv=const_cast<double*>(vd+i);
*pc=10;
*pv=11;
}
for(int k=0;k<5;k++)
{
cout<<"cd["<<k<<"]:"<<cd[k]<<endl;
cout<<"vd["<<k<<"]:"<<vd[k]<<endl;
}
}


那为什么这段代码里 原来的数组元素也是const的,为什么里面的值变了呢??
l176266956 2008-10-27
  • 打赏
  • 举报
回复
觉得你应该多看看其它的贴.http://topic.csdn.net/u/20081024/19/a2ae27b7-6916-4afe-b7b9-f72644c14a0a.html
这个地址的问题和你类似.下面是我觉得应该是正确的答案:
1.为什么可以修改&a地址的内容;
因为你把它强制转换为int *类型了,虽然原来是const的,但强制转换后就不一样了。这个问题Bruce Eckle在他的《c++编程思想 第一卷》中的常量一章中讨论过,我记得对于这种情况他的评论为:虽然c++有助于防止错误的发生(指类型检查),但程序员自己打破这种安全机制,那它也是无能为力的。
2.同一个地址(ptr和&a一样),为什么(*ptr <>a)
这里ptr和&a不是完全一样的,一般c++不会为常量分配内存空间,而是通过常量折叠的方式处理。但在程序中如果取了常量的地址,那么就会强制c++为其分配内存,这里又不能打破常量不能被改变的限制,所以后来强制为其分配的空间和原来的常量已经不是同一个地址了。
这个"常量折叠"是在编译器进行语法分析的时候,将常量表达式计算求值,并用求得的值来替换表达式,放入常量表。可以算作一种编译优化
因为编译器在优化的过程中,会把碰见的const全部以内容替换掉(跟宏似的: #define PI 3.1415,用到PI时就用3.1415代替),这个出现在预编译阶段;但是在运行阶段,它的内存里存的东西确实改变了!!!但当你只调用a时,它不会去读地址,除非你显式去调用地址.如果你加上一句cout < < *(int *)&a < <endl;的话,你将得到19.
NesTa_xP 2008-10-27
  • 打赏
  • 举报
回复
#include<iostream>
using namespace std;
int main()
{
const double cd[5]={1,2,3,4,5};
volatile double vd[5]={1,2,3,4,5};
double* pc;
double* pv;
for(int i=0;i<5;i++)
{
pc=const_cast<double*>(cd+i);
pv=const_cast<double*>(vd+i);
*pc=10;
*pv=11;
}
for(int k=0;k<5;k++)
{
cout<<"cd["<<k<<"]:"<<cd[k]<<endl;
cout<<"vd["<<k<<"]:"<<vd[k]<<endl;
}
}


那么请问一下 为什么这个cd[]和vd[]数组里面输出的值不是以前数组的值呢?而是修改后的10,和11
lann64 2008-10-27
  • 打赏
  • 举报
回复
看看这个程序
#include <iostream>

using namespace std;

int main()
{
const int a=10;
const int* pc=&a;
int* p=const_cast <int*>(&a);

cout<<"befor: ";
cout <<"a: "<<a;
cout <<" *pc: "<<*pc<<endl;

(*p)=1;

cout<<"after: ";
cout <<"a: "<<a;
cout <<" *pc: "<<*pc<<endl;

return 0;
}
elmnd 2008-10-27
  • 打赏
  • 举报
回复
一开始就是常量了啊~!
kingcard 2008-10-27
  • 打赏
  • 举报
回复
楼主,这样解释的:
const 属于编译时常量,也即是在编译期间,编译器会自动通过必要的计算,把复杂的表达式变成简单的值。
比如,你前面这样定义了:
const int iFuck = 0x100;
const int iShit = ((iFuck * 4) & 0xFFFFFFFF) * 0x12345678;
编译器在编译时就会根据 iFuck 的值来计算 iShit 的值,然后把 iShit 看做一个常数。这个过程就是所谓的 “常量折叠”。

我们再看楼主最初给出的代码:
#1 const int a=10;
#2 int* p=const_cast <int*>(&a);
#3 *p=1;
#4 cout < <a;

当编译器看到第一行时,就知道 a 是一个常量;通常情况下,C++ 编译器并不为常量分配内存空间的,它就把它当做:#define a 10 这样使用,直接用值替代所有引用 a 的地方,所以第4行,输出的数值就是 10。
即使C++编译器看到第二行时,int *p = const_cast<int*>(&a),它暗骂了一声:我顶你个肺,你明明要把a当做常量,现在又搞东搞西,用一个变量指针引用它,这不是坑我编译器吗?
当然,它嘀咕是嘀咕,根据C++语法,它照样往下走。
然后看到第三行:*p = 1。是这样的,如果前面的定义 const int a = 10 放在函数体内,因为一般debug版时,编译器看到它(a)被引用了(因为第2行取了const值的地址),所以会为它(a)在堆栈上分配内存,所以执行完 *p = 1 后,不仅 *p 确实等于 1,此时堆栈上对应“a”的单元也等于1。注意,这只是堆栈单元,不是a,前面说了,a已经被替换为10了,所以第4行会直接输出4.
此外,如果 const int a = 10 放在函数体外,编译器就不会让你如此“胡作非为”的,它把const当做“只读”单元,所以执行道第3行,程序崩溃。



再说说楼主的后面贴的代码:如果const是数组或结构体,C++编译器会直接分配内存,不是使用堆栈临时单元了,所以会生效,此外,如果const放在函数体外,其命运跟上面一样的。
啰嗦完毕!
lann64 2008-10-26
  • 打赏
  • 举报
回复
的确是把常量性消除了。可惜你这里用的是简单内置类型,编译器在编译的时候把所有看到的a都替换成了10,你再修改a存储的值也没用了,运行时已经没有取值的动作了。所以看不出来了。
其实你输出*p就看出来了。
甚至再弄个const int* pc出来看,就更清楚看出,(*p)=1;的确是把存储的内容修改了。
hityct1 2008-10-26
  • 打赏
  • 举报
回复
mark
太乙 2008-10-26
  • 打赏
  • 举报
回复



我的vc6.0


9: cout <<a;
0040155E push 0Ah
00401560 mov ecx,offset std::cout (0047ff88)
00401565 call @ILT+240(std::basic_ostream<char,std::char_traits<char> >::operator<<) (004010f5)


注意:
0040155E push 0Ah

我想是编译器做了优化,对于const类型的东西,编译的时候直接用其代表的常量值替换了!






NesTa_xP 2008-10-26
  • 打赏
  • 举报
回复
#include<iostream>
using namespace std;
int main()
{
const double cd[5]={1,2,3,4,5};
volatile double vd[5]={1,2,3,4,5};
double* pc;
double* pv;
for(int i=0;i<5;i++)
{
pc=const_cast<double*>(cd+i);
pv=const_cast<double*>(vd+i);
*pc=10;
*pv=11;
}
for(int k=0;k<5;k++)
{
cout<<"cd["<<k<<"]:"<<cd[k]<<endl;
cout<<"vd["<<k<<"]:"<<vd[k]<<endl;
}
}


那么请问一下 为什么这个cd[]和vd[]数组里面输出的值不是以前数组的值呢?而是修改后的10,和11
love_xx 2008-10-26
  • 打赏
  • 举报
回复
a的内容根本就没有改变过

int *p = const_cat <int *>(&a);
这个赋值只是将 指针P指向a的内容。

*p = 1;
跟上面做了同样的事情。

全过程变量a的值都没有改变
  • 打赏
  • 举报
回复
因为不管你怎么改,只要你写a那就是10
编译的时候都已经写死了10这个数值了.
arong1234 2008-10-26
  • 打赏
  • 举报
回复
我的理解是这个cast只是修改语义上是常量而实际上不是常量的东西。例如,一个函数接口是const int & a,你传一个菲const的整型变量进去,可以这么修改。

对于const int类型,它在编译时就可能已经被替换了,也许根本不会给它分配内存,更何况地址。

64,637

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧