通过"int *"指针更改"const int"。令人惊讶和有趣

Change "const int" via an "int *" pointer. Surprising and interesting

本文关键字:int const 指针 通过      更新时间:2023-10-16

可能重复:
通过非常量指针修改常量

让我们先看看下面的代码。每个短代码:

int main()
{
    const int n=9;
    int *p=(int*)&n;
    *p=5;
    cout<<*p<<endl; //result is 5
    cout<<n<<endl;  // 9
    int a=n+1;
    cout<<a<<endl;  // 10
}

令我惊讶的是,编译器一点也不抱怨。结果正如我所展示的评论
但是,如果这或多或少有道理的话。更令人惊讶的是,当您调试它时,您可以看到n的值实际上已经更改为5
但是,当你使用"n"时,似乎"n"仍然被视为原始值9
所以我猜编译器已经把"n"的原始值存储在其他地方了,对吧?那么,"n"的原始值,即9,现在存储在哪里
谢谢你的帮助!

这可能是由于优化。既然您声明了const int n=9,那么您基本上就是在承诺不会修改n。因此编译器可以自由地将cout << n << endl;优化为简单的cout << 9 << endl;。我不认为旧的价值存储在其他地方。

然而,这是未定义的行为

我可以确认,这种行为的原因是优化,即使是在调试构建中:

    cout<<n<<endl;  
01151426  mov         esi,esp  
01151428  mov         eax,dword ptr [__imp_std::endl (11582B4h)]  
0115142D  push        eax  
0115142E  mov         edi,esp  
//HERE:
//
01151430  push        9  
//
//
01151432  mov         ecx,dword ptr [__imp_std::cout (11582B0h)]  
01151438  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (11582ACh)]  
0115143E  cmp         edi,esp  
01151440  call        @ILT+325(__RTC_CheckEsp) (115114Ah)  
01151445  mov         ecx,eax  
01151447  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (11582A8h)]  
0115144D  cmp         esi,esp  
0115144F  call        @ILT+325(__RTC_CheckEsp) (115114Ah)  

n甚至没有进入讨论。

如果n不是const,则优化将是非法的:

00D51426  mov         esi,esp  
00D51428  mov         eax,dword ptr [__imp_std::endl (0D582B4h)]  
00D5142D  push        eax  
00D5142E  mov         edi,esp  
//HERE
//
00D51430  mov         ecx,dword ptr [n]  
00D51433  push        ecx  
//
//
00D51434  mov         ecx,dword ptr [__imp_std::cout (0D582B0h)]  
00D5143A  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (0D582ACh)]  
00D51440  cmp         edi,esp  
00D51442  call        @ILT+325(__RTC_CheckEsp) (0D5114Ah)  
00D51447  mov         ecx,eax  
00D51449  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (0D582A8h)]  
00D5144F  cmp         esi,esp  
00D51451  call        @ILT+325(__RTC_CheckEsp) (0D5114Ah)  

这里,n的值被推送到参数堆栈上,因为它不是const