诡异的const 你真的懂吗???
A、在C++编译器中:const int a=10;int *b=(int*)&a;std::cout<<a<<std::endl;//输出10(*b)=1;std::cout<<a<<std::endl;//输出10B、在C编译器中:const int a=10;int *b=(int*)&a;printf("%d\n",a);//输出10(*b)=1;printf("%d\n",a);//输出1那位大牛能解释一下,为什么这样啊?const 修饰的变量 在C和C++里面不同。我一直认为 A根本编译不过,因为C++中的const 就是把a变成了常量,改变 是编译不过的,可是事实是通过编译了,在C里面编译通过还可以理解,因为C中const 修饰的 只能说明是只读的,是可以修改其值的,求解???在 A中为什么能编译通过,而且在C与C++中结果不同???
不知道对不对啊 我的理解是:
const int a=10 当操作系统执行了这条指令 就已经为变量a分配了内存空间了 也证明a有了一个地址
那就可以理解 int *b = (int *)&a;操作系统执行这句语句是将 const int a 强制转换为指针变量了 然后把
系统分配给a的地址赋值给了 *b ,也就是说 a的值并没有发生变化 *b只是得到了 a的地址
所以后面的两句输入都应该还是 a的原来的值 10
a作为常量 值一直没有发生变化 它与b之间没有做值传递只是做了地址之间的赋值
a还继续保留了自己原有的值和地址, b的地址里面存放了a的地址而已
所以是应该可以通过编译的
如果说的有误请大牛纠正 感谢 梦想与现实 发表于 2012-9-14 19:29 static/image/common/back.gif
不知道对不对啊 我的理解是:
const int a=10 当操作系统执行了这条指令 就已经为变量a分配了内存空间了 也 ...
可以编译通过,但是 在c和C++里面结果不一样,从我反汇编的结果来看,不管在c还是c++的里面在*b赋值之后 a的存储空间的值确实是改变了,只是到输出这一步的时候,在C里面会再一次的读a所在内存的内的值,而在C++里面,则是直接把a原来的值 拿来用 没有再一次去读a所在内存内的值!!估计是编译器的在不同语言下的方式不一样吧在C++里面 如果把const 改为volatile 就能输出和C一样的效果啦!从这更能断定是编译器在搞鬼,在C++里不告诉编译器 a是容易改变的值 他就只读一次 就认为不会变!哎 实在是难搞啊 害的我面试题都做错了 const int a=10;
int *b=(int*)&a;
std::cout<<a<<std::endl;//输出10
(*b)=1;
std::cout << a << std::endl;//输出10
std::cout << *((int *)&a) << std::endl;//输出1a的值确实改变了,c++里int *b=&a;是不允许的,但是这里进行了类型转换,
骗过了编译器。当输出a的值时,编译器看到a是const类型的,就不会从它的内存
读数据压栈,而是直接把那个10压栈,可能默认const类型值不能改变。所以输出10.
当访问a内存里数据时其实已经变为1了。 呜呜。。没分了。。LZ都说光了 无星之夜 发表于 2012-9-14 20:36 static/image/common/back.gif
呜呜。。没分了。。LZ都说光了
那只是我的认为,希望各位仁兄各抒己见哦! 据说是因为c++对指针用法的限制~~~~ msdn的说法:
In C++, you can use the const keyword instead of the #define preprocessor directive to define constant values.
这是不是在说:C++里的const相当于#define,所以 std::cout<<a<<std::endl;//输出10
而C里面没有这个效果。 贝壳 发表于 2012-9-15 10:23 static/image/common/back.gif
msdn的说法:
In C++, you can use the const keyword instead of the #define preprocessor directive to ...
我感觉那句话的意思 是最好用const代替宏定义在C++里面 而不是等价的意思! 是这样的:
1.在C语言里,const修饰的并不是真正的常量,仅仅是不可写的变量。举个例子,C数组的长度必须是常量表达式,你写
int v;正确
而
const int N = 10;
int v;就错误。
2.在C++里,const修饰的是真的常量,该常量并没有实际分配存储单元,而是在编译的时候直接将常量出现的位置替换为常量的值,这个称为“常量折叠”。所以前面的例子在C++里可以编译通过。
3.最容易令人产生疑问的地方在于:C++中,你居然可以对常量取地址(前面说到不为常量分配存储单元,如何还能取常量的地址呢?)
当C++中对常量单元取地址时,编译器就会在内存中复制一份该常量的副本,通过这个地址是无法改变常量的值的,因为该地址只是一个常量的副本。 仰望天上的光 发表于 2012-9-15 13:08 static/image/common/back.gif
是这样的:
1.在C语言里,const修饰的并不是真正的常量,仅仅是不可写的变量。举个例子,C数组的长度必须是 ...
但是从反汇编后 看的话 值确实是被改变了啊,只是再次输出a的值的时候,编译器没有再去那个地址读数据,而是根据自己的"经验" 直接输出原来的值! 拉登o睡觉 发表于 2012-9-15 14:16 static/image/common/back.gif
但是从反汇编后 看的话 值确实是被改变了啊,只是再次输出a的值的时候,编译器没有再去那个地址读数据, ...
我不是说了,改变的是副本的值了吗?原先的常量没有被分配空间。这个和你看到的现象是一致的。 仰望天上的光 发表于 2012-9-15 17:11 static/image/common/back.gif
我不是说了,改变的是副本的值了吗?原先的常量没有被分配空间。这个和你看到的现象是一致的。
但是 从反汇编看 定义语句 确实分配了空间啊 对于本程序是存储在ebp-4的位置 分配空间是由于这个程序段const int a=10;之后含有&a这样的代码。
我前面说过,当对常量取地址的时候。编译器将会为该常量创建一个副本,这个空间是为这个副本分配的。
至于为什么此时要分配空间,我的理解是:你都已经对常量取地址了,天晓得你后面要不要读这个地址的内容;不如分配个空间作为常量的副本,这样你读该地址内容的时候就不会出问题。 const int a=10;的处理你在汇编代码中是看不到的,因为在编译的时候做了“常量折叠”处理,类似于C中的宏替换,所有出现a的地方都被10替换了。所以你看到的分配空间,就是给该常量副本分配的空间,与该常量没有任何关系。 学习了 仰望天上的光老师 一直是我的偶像啊{:5_107:} 过来学习一下。。。。 学习了,很深奥的样子 楼上的解释的好详细啊
页:
[1]