const volatile 和 const 问题的探究

jiangmuchen 2012-09-03 11:04:25
请来看这么一个例子:
C++代码:
const int n=100;
int*nn=const_cast<int*>(&n);
*nn=111;
cout<<n<<endl;//输出1
cout<<*nn<<endl;//输出2
cout<<&n<<endl;//输出3
cout<<nn<<endl;//输出4
-------------------
输出1:100
输出2: 111
其实从规则上,我知道这种现象是正常的。应该这个n没有volatile修饰。
于是我猜想,产生这种结果的可能是n的地址和nn的值可能不等。
但是输出3和输出4的值却是相等的。
再看一个例子:
const volatile int n=100;
int*nn=const_cast<int*>(&n);
*nn=111;
cout<<n<<endl;//输出1
cout<<*nn<<endl;//输出2
cout<<&n<<endl;//输出3
cout<<nn<<endl;//输出4
-----------------
输出1:111
输出2:111
这没什么好说的了。
问题是输出3的结果是1.
他的地址是1.这如何解释。

综上,我有两个问题:
问题1:为什么例子1里面的输出3和4的地址一样,输出1,2的结果却不一样。
问题2:为什么例子2中,输出3的值是1.

...全文
110 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
赵4老师 2012-09-04
  • 打赏
  • 举报
回复
无对应汇编指令,无真相!
赵4老师 2012-09-04
  • 打赏
  • 举报
回复
VC调试(TC或BC用TD调试)时按Alt+8、Alt+6和Alt+5,打开汇编窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应内存和寄存器变化,这样过一遍不就啥都明白了吗。
对VC来说,所谓‘调试时’就是编译连接通过以后,按F10或F11键单步执行一步以后的时候,或者在某行按F9设了断点后按F5执行停在该断点处的时候。
(Linux或Unix下可以在用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。)
想要从本质上理解C指针,必须学习汇编以及C和汇编的对应关系。
从汇编的角度理解和学习C语言的指针,原本看似复杂的东西就会变得非常简单!
指针即地址。“地址又是啥?”“只能从汇编语言和计算机组成原理的角度去解释了。”

这辈子不看内存地址和内存值;只画链表、指针示意图,画堆栈示意图,画各种示意图,甚至自己没画过而只看过书上的图……能从本质上理解指针、理解函数参数传递吗?本人深表怀疑!
这辈子不种麦不收麦不将麦粒拿去磨面;只吃馒头、吃面条、吃面包、……甚至从没看过别人怎么蒸馒头,压面条,烤面包,……能从本质上理解面粉、理解面食吗?本人深表怀疑!!

提醒:
“学习用汇编语言写程序”

“VC调试(TC或BC用TD调试)时按Alt+8、Alt+6和Alt+5,打开汇编窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应内存和寄存器变化,这样过一遍不就啥都明白了吗。
(Linux或Unix下可以在用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。)
想要从本质上理解C指针,必须学习C和汇编的对应关系。”
不是一回事!

不要迷信书、考题、老师、回帖;
要迷信CPU、编译器、调试器、运行结果。
并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。
任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实!

有人说一套做一套,你相信他说的还是相信他做的?
其实严格来说这个世界上古往今来所有人都是说一套做一套,不是吗?

不要写连自己也预测不了结果的代码!

不要纠结各种常量了,这个世界上唯一不变的就是变化。用API WriteProcessMemory还能修改正运行的其它进程的内存里面的所谓常量呢!
pengzhixi 2012-09-04
  • 打赏
  • 举报
回复
直接谷歌常量折叠 另外还有个名词叫优化,而volatile可以阻止这样的优化
yisikaipu 2012-09-04
  • 打赏
  • 举报
回复
问题1里
cout<<n<<endl;
被编译器直接替换为
cout<<100<<endl;

所里运行时这里与n毫无关系了

问题2里
volatile一定程序上阻止了编译器擅自替换

但cout/ostream没有处理volatile修饰类型的函数,它把&n转换成了BOOL,n的地址总是大于0,所以转成出的BOOL总是1

改一下即可
cout<<(void*)&n<<endl;
乃不知有汉 2012-09-04
  • 打赏
  • 举报
回复
cout<<n<<endl;

const int n=100;
你告诉编译器n是常量
编译器很开心的优化
直接安插了 cout<< 100 <<endl;

const volatile int n=100;
由于是 volatile, 编译器不会对其优化
故 cout<< n <<endl;
jiangmuchen 2012-09-04
  • 打赏
  • 举报
回复
人工置顶一下,求解答。
jiangmuchen 2012-09-04
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 yisikaipu 的回复:]

问题1里
cout<<n<<endl;
被编译器直接替换为
cout<<100<<endl;

所里运行时这里与n毫无关系了

问题2里
volatile一定程序上阻止了编译器擅自替换

但cout/ostream没有处理volatile修饰类型的函数,它把&n转换成了BOOL,n的地址总是大于0,所以转成出的BOOL总是1

改一下即可
cout<<(void……
[/Quote]
最直接,最透彻,最明了,谢谢。
jiangmuchen 2012-09-04
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 的回复:]

VC调试(TC或BC用TD调试)时按Alt+8、Alt+6和Alt+5,打开汇编窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应内存和寄存器变化,这样过一遍不就啥都明白了吗。
对VC来说,所谓‘调试时’就是编译连接通过以后,按F10或F11键单步执行一步以后的时候,或者在某行按F9设了断点后按F5执行停在该断点处的时候。
(Linux或Unix下可以在用GDB调试时,看每句C……
[/Quote]
ok,我先把你这段保存下来。
jiangmuchen 2012-09-04
  • 打赏
  • 举报
回复
嗯,谢谢。
[Quote=引用 2 楼 的回复:]

cout<<n<<endl;

const int n=100;
你告诉编译器n是常量
编译器很开心的优化
直接安插了 cout<< 100 <<endl;

const volatile int n=100;
由于是 volatile, 编译器不会对其优化
故 cout<< n <<endl;
[/Quote]

64,677

社区成员

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

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