读书人

关于const变量的改变,该如何解决

发布时间: 2012-08-17 02:08:34 作者: rapoo

关于const变量的改变
const int a = 0;
int *p =(int *)&a;
*p = 1;

VC下输出a的值还是0,但是内存单元中已经是1;
linux下a输出是1;
请各位前辈指点。

[解决办法]
未定义行为
看编译器吧
参考常量折叠,坛子里有太多的这种帖子了。
[解决办法]
你可以试一下,&a和p的内存地址值是否一样;
[解决办法]
尝试修改(直接或间接)const 类型的变量 行为未定义

百度 未定义行为.
[解决办法]
我是来看解释的,楼下继续解答
[解决办法]
具体的看编译器怎么去实现这个的了。
[解决办法]
const int a = 0;
int temp = a;
编译器便宜后的代码其实是
int temp = 0;
编译器会直接用常量0替换a
[解决办法]

探讨
const int a = 0;
int temp = a;
编译器便宜后的代码其实是
int temp = 0;
编译器会直接用常量0替换a

[解决办法]
常量折叠, 垃圾设置, 毫无意义.

楼主的代码不规范,应当这么做:

PHP code
#include <iostream>using namespace std;int main(int argc, char* const argv[]) {        const int n = 1;        int *p_n = const_cast<int*>(&n);        *p_n = 2;        cout<<n<<endl<<*p_n<<endl;        return 0;}
[解决办法]
对于VC++,程序中所有的const类型变量都已经在编译的时候被替换为了常量值。
const int a = 0;
int *p =(int *)&a;
*p = 1;
cout<<*p<<" "<<a<<endl;
编译处理的实际是cout<<*p<<" "<<0<<endl;
但内存中仍然存在a的内存空间。
int *p =(int *)&a;
*p = 1;
这两句话也确实会改变a所占内存空间内的值。
对于gcc而言,他的处理有所不同的就是,常量在编译的时候没有做处理,但这样处理会经常产生一些难以排查的错误。
C++标准并没有对const的这种处理没有做强制规定,因此gcc和vc++两种编译器的处理都不能算错误,也不能说gcc就是100%标准,vc++就是错误。
个人更加偏好于vc++的处理,即使修改const,也不会产生违背const语义的操作
[解决办法]
const int a = 0;说明a是一个常量,不可以修改。但没说不可以通过其他间接修改。指针p是指向a的地址,通过*p是可以修改的。
[解决办法]
两者地址是一样的,这么做并不好,是未定义行为,具体情况根据编译器不同
[解决办法]
还是看它的汇编代码更清楚:
52: const int a = 1;
00401308 mov dword ptr [ebp-4],1
53: int *p = (int *)&a;
0040130F lea eax,[ebp-4]
00401312 mov dword ptr [ebp-8],eax
54: *p = 10;
00401315 mov ecx,dword ptr [ebp-8]
00401318 mov dword ptr [ecx],0Ah
55: printf("a = %d\n", a);
0040131E push 1 ===》(亮点在这里)
00401320 push offset string "a = %d\n" (0043101c)
00401325 call printf (00408370)
0040132A add esp,8
[解决办法]
55: printf("a = %d\n", a);
0040131E push dword ptr [ebp-4] ===》如果是这样的,则会是10
00401320 push offset string "a = %d\n" (0043101c)
00401325 call printf (00408370)
0040132A add esp,8
[解决办法]
。。。 好像前两天看到过这样的帖子,常量折叠吧,出现问题的原因在于书写不规范
[解决办法]
没事研究这个干什么啊?
既然是const,为啥还要用指针转换出来修改?吃饱了撑的
------解决方案--------------------


常量折叠?错了,上面兄弟已经回复了,是编译器的问题。
[解决办法]
经vc6测试, 两者输出均为1.
与编译器有关。
[解决办法]
才刚吵了两天.......

我就纳闷儿了,你没事去改const量做啥呢?闲得蛋疼了?
[解决办法]
不要纠结各种常量了,这个世界上唯一不变的就是变化。用API WriteProcessMemory还能修改正运行的其它进程的内存里面的所谓常量呢!

[解决办法]
VC下面在编译的时候直接拿0把变量a给替换了吧!而在linux下面没做。

结果是什么看编译器的实现,不过为什么要写这样的代码呢?
[解决办法]
我在VC6.0下运行是1
[解决办法]
错了也是0,
[解决办法]

探讨

才刚吵了两天.......

我就纳闷儿了,你没事去改const量做啥呢?闲得蛋疼了?

[解决办法]
无可奈何啊,神经病代码无穷无尽。
[解决办法]
哎,可怜啊,没有好老师,没有好教材的兄弟们,要学个编程真难啊。
[解决办法]
没那么难吧?以前我们都是自学,不但没老师,连同学都没一个。书店里连相关书籍都找不到,还得靠邮购。现在有了互联网,要找什么书什么资料那得方便千万倍啊!

当初好不容易弄到一本老外写的BASIC教程,一翻开就被Hello World弄得呆痴痴的——话说这啥书啊?咋什么基础知识都没讲就先来个看不懂的玩意儿?嘿嘿,好在当时还能认出26个字母,要不得打退堂鼓了。

那本书被我彻底翻烂了,不过BASIC倒也学会了——自以为的,因为没机器,没法上机验证。好处就是练出来能在脑袋里模拟程序运行的本事。呵呵
[解决办法]
语言说了不能这么干,也就是说这么干了后果自负。
所以偏要这么干,干了后出现理解不了的情况又要求解释,这这这……
[解决办法]
我实验的时候,使用gcc的时候没有使用常量折叠,使用g++的时候使用了常量折叠
const在C++中和C中还是有些不同的,在C中是不可修改的量,不是常量,而在C++是常量
[解决办法]
探讨

哎,可怜啊,没有好老师,没有好教材的兄弟们,要学个编程真难啊。

[解决办法]
探讨

没事研究这个干什么啊?
既然是const,为啥还要用指针转换出来修改?吃饱了撑的

[解决办法]
编译器在涉及到const的常量在编译时直接用值代替了,所以你输出a的值可定没有变化是0,但在内存里你改变了其值为1了。你理解编译器工作原理就好理解了。
[解决办法]
编译器拿a当常量,根本不计算,就直接输出了.

[解决办法]
C++里的常量分为编译期常量和运行期常量

编译期常量没有内存地址。
如果一个表达式里面的所有运算数都是编译期常量,则此表达式也是编译期常量,此概念是递归的。
使用编译期常量的地方,经过编译后,其对应的机器指令为立即数。
编译期常量可以用于枚举类型时的赋值,或用来定义数组
如:
enum { xxx = compile_const_num };
int ar[compile_const_num];


运行期常量是有内存地址的,其存放地点可能是只读内存区(如字符串常量),
也可能是普通内存区(如普通常量C++大型对象),编译器保证使用常规方法
无法对其进行修改。

const int a = 1;
直接使用a的话,它编译期常量,任何C++编译器都会是直接使用立即数1

顺带说一下sizeof(xxxx)、模板参数template<int n>的n,都是编译期常量

[解决办法]
探讨
练出来能在脑袋里模拟程序运行的本事

[解决办法]
看具体编译器的。
[解决办法]
常量区不可改变
[解决办法]
探讨

语言说了不能这么干,也就是说这么干了后果自负。
所以偏要这么干,干了后出现理解不了的情况又要求解释,这这这……



[解决办法]
探讨

哎,可怜啊,没有好老师,没有好教材的兄弟们,要学个编程真难啊。

[解决办法]
探讨

哎,可怜啊,没有好老师,没有好教材的兄弟们,要学个编程真难啊。

[解决办法]
C++常量折叠特性可能会使a完全没有地址。所以代码本身就是有问题的。不必去探究这种错误行为的后果吧,知道这是错误的就行了。

读书人网 >C++

热点推荐