相同内存地址的两个不同值

时间:2010-08-29 05:44:15

标签: c++

代码

#include <iostream>
using namespace std;

int main() {
    const int N = 22;
    int * pN = const_cast<int*>(&N);
    *pN = 33;
    cout << N << '\t' << &N << endl;
    cout << *pN << '\t' << pN << endl;
}

输出

  

22 0x22ff74

     

33 0x22ff74

为什么同一地址有两个不同的值?

7 个答案:

答案 0 :(得分:21)

  

为什么同一地址有两个不同的数据?

没有。允许编译器优化对const的任何提及,就好像你已经在其中编写了编译时值。

请注意,编译器也可以生成代码,当你运行它时会擦除你的硬盘,如果你做了一些讨厌的技巧,比如写入为consts保留的内存。

答案 1 :(得分:10)

您在行*pN = 33;上获得了未定义的行为,因为您正在修改const值。任何事情都可能发生。不要这样做。


但是,很可能,您的编译器只是进行了优化。在该行:

cout << N << '\t' << &N << endl;

它知道N是一个值为22的常量表达式,所以只需将该行更改为:

cout << 22 << '\t' << &N << endl;

在下一行中,您将获取N地址的值,您将其“设置”为33。(但实际上,您所做的只是删除了有关程序状态的任何保证。)

答案 2 :(得分:5)

通过声明N是const,您承诺不会修改它。然后你去修改它。这打破了编译器所做的一个假设,因此,程序行为不正确。

这被称为“未定义的行为” - 在违反语言假设后,程序的行为完全未定义。它不需要产生那个输出 - 它可以为两者产生33,或者42,或者崩溃,或者擦除你的硬盘驱动器,或通过你的鼻腔传唤召唤恶魔。所以,不要修改const值:)

答案 3 :(得分:3)

int * pN = const_cast<int*>(&N);
*pN = 33;

您的代码调用未定义的行为 1 ,因为您正在修改const限定变量/对象的内容。

<子> 1) 未定义的行为:行为,例如在使用时可能出现的行为     错误的程序构造或错误的数据,其中     标准没有要求。[注意:允许的未定义行为     范围从完全忽略情况与不可预测     结果,在翻译或程序执行期间表现     记录的环境特征(有或没有     发布诊断消息),终止翻译     或执行(发出诊断信息)。

答案 4 :(得分:0)

在代码中使用const_cast,只需将指针“Pn”移交给“N”,通过它可以修改“N”。 'N'的地址与移交指针'Pn'

保持一致

答案 5 :(得分:0)

您可以将N声明为volatile,以强制编译器从变量的内存位置获取当前值。

"aggs" : { "names":{ "terms":{ "field":"commodity_line.keyword", "include" : "3.*" } }

答案 6 :(得分:0)

我有相同的问题(Why am I not able to modify the contents of const int even with const_cast<int*>?)。我认为每个人都很好地回答了这个问题。只需添加编译器的程序集输出

这是我的原始代码

const int y = 7;
int* a = new int;
a = const_cast<int*>(&y); 
*a = 8;
std::cout << (int)*(&y) << std::endl;

这是程序集输出

std::cout << (int)*(&y) << std::endl;
00381CB6  push        offset std::endl<char,std::char_traits<char> > (03813C5h)  
**00381CBB  push        7**  
00381CBD  mov         ecx,dword ptr [_imp_?cout@std@@3V?$basic_ostream@DU?$char_traits@D@std@@@1@A (03900ACh)]  
00381CC3  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (03900B8h)]  
00381CC9  mov         ecx,eax  
00381CCB  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (03900BCh)]  

因此,编译器将在编译期间将const变量替换为其实际值。