C++-具有相同的地址但值不同这是为何?

C++-具有相同的地址但值不同这是为何?

晚风撩人 发布于 2017-08-15 字数 516 浏览 1403 回复 6
#include <iostream>
using namespace std;

int abc(int argc, _TCHAR* argv[])
{
const int a1 = 1;
int *p2 = const_cast<int*>(&a1);
*p2 = 2;

cout << "value a1="<< a1 << endl;
cout << "value *p2=" <<*p2 << endl;
cout << "address a1=" <<&a1 << endl;
cout << "address p2=" <<p2 << endl;

return 0;
}

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

瑾兮 2017-10-24 6 楼

编译器优化,进行了数据暂存,加volatile修饰,强制每次由内存读取数据.

夜无邪 2017-10-13 5 楼

const的值是不能重新赋值的!即定义好了一个const的变量,这个变量的值一定是不变的,这是C++的const特性,否则const存在的意义也就没了!
而const_cast可以称为"未定义行为(Undefined Behavior)",所谓未定义,是说这个语句在标准C++中没有明确的规定,由编译器来决定如何处理。
C++中某些时候函数可能声明了一个不是const的参数,而需要传进去的实际参数却是const的,但是我们知道这个函数是不会对参数做修改的。于是我们就需要使用const_cast去除const限定,以便函数能够接受这个实际参数。
还有另一种情况,当定义一个变量的时候,它的地址是一个const的引用,当要修改这个变量的值的时候可以用const_cast,这样可以改变该变量的值,地址仍然是指向const。

晚风撩人 2017-10-07 4 楼

const_cast<int>,对变量强制转换会取消变量CV属性,所以加了volatile,也是这个结果,我以前也做过类似的问题,你比我想得更多

浮生未歇 2017-09-21 3 楼

常量折叠。在编译器里进行语法分析的时候,将常量表达式计算求值,并用求得的值来替换表达式,放入常量表,可以算作一种编译优化。
扩展阅读: http://www.cnblogs.com/likebeta/archive/2012/04/06/2435136.html

浮生未歇 2017-09-08 2 楼

直接看汇编代码就可以看出问题端倪:
问题出在编译器对两条cout语句的处理

; 12 : cout << "value a1="<< a1 << endl;

mov esi, esp
mov eax, DWORD PTR __imp_?endl@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@1@AAV21@@Z
push eax
mov edi, esp
push 1
push OFFSET ??_C@_09MAANFLFL@value?5a1?$DN?$AA@
mov ecx, DWORD PTR __imp_?cout@std@@3V?$basic_ostream@DU?$char_traits@D@std@@@1@A
push ecx
call ??$?6U?$char_traits@D@std@@@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@0@AAV10@PBD@Z ; std::operator<<<std::char_traits<char> >
add esp, 8
mov ecx, eax
call DWORD PTR __imp_??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@H@Z
cmp edi, esp
call __RTC_CheckEsp
mov ecx, eax
call DWORD PTR __imp_??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@P6AAAV01@AAV01@@Z@Z
cmp esi, esp
call __RTC_CheckEsp

; 13 : cout << "value *p2=" <<*p2 << endl;

mov esi, esp
mov eax, DWORD PTR __imp_?endl@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@1@AAV21@@Z
push eax
mov edi, esp
mov ecx, DWORD PTR _p2$[ebp]
mov edx, DWORD PTR [ecx]
push edx
push OFFSET ??_C@_0L@JBEGNMKE@value?5?$CKp2?$DN?$AA@
mov eax, DWORD PTR __imp_?cout@std@@3V?$basic_ostream@DU?$char_traits@D@std@@@1@A
push eax
call ??$?6U?$char_traits@D@std@@@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@0@AAV10@PBD@Z ; std::operator<<<std::char_traits<char> >
add esp, 8
mov ecx, eax
call DWORD PTR __imp_??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@H@Z
cmp edi, esp
call __RTC_CheckEsp
mov ecx, eax
call DWORD PTR __imp_??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@P6AAAV01@AAV01@@Z@Z
cmp esi, esp
call __RTC_CheckEsp

在处理const int a1时,编译器是直接push一个立即数1,
即:push 1
而在处理*p时,编译器增加了3条语句:
mov ecx, DWORD PTR _p2$[ebp]
mov edx, DWORD PTR [ecx]
push edx
即从内存中取值后再push

归属感 2017-08-25 1 楼

加volatile可以强制每次读写变量值都从内存读取。

const int a1 = 1;
int p2 = const_cast<int>(&a1);
*p2 = 2;

int e = a1 + a1;
mov dword ptr [ebp-20h],2
编译器直接把a1当立即数使用了。