鱼C论坛

 找回密码
 立即注册
查看: 1387|回复: 8

[已解决]关于c++常量修改的问题

[复制链接]
发表于 2019-3-14 14:51:11 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
#include <iostream>
using namespace std;
int main(int argc, char const *argv[])
{
    /* code */
    const int a=1;
    cout <<&a<<endl;
    int *p=(int *)&a;
    *p=20;
    cout << a<<endl<<&a<<endl<<p<<endl<<*p<<endl<<*(&a)<<endl;
    return 0;
}
我用的是MinGW-W64,这个a打印出来是1,但是*&a是20,???/
最佳答案
2019-3-14 15:18:13
        cout << a << endl << &a << endl << p << endl << *p << endl << *(&a) << endl;
002E6B27  mov         esi,esp  
002E6B29  push        offset std::endl<char,std::char_traits<char> > (02E1410h)  
002E6B2E  mov         edi,esp  
002E6B30  push        1  
002E6B32  mov         ebx,esp  
002E6B34  push        offset std::endl<char,std::char_traits<char> > (02E1410h)  
002E6B39  mov         eax,esp  
002E6B3B  mov         ecx,dword ptr [p]  
002E6B3E  mov         edx,dword ptr [ecx]  
002E6B40  push        edx  
002E6B41  mov         ecx,esp  
002E6B43  push        offset std::endl<char,std::char_traits<char> > (02E1410h)  
002E6B48  mov         edx,esp  
002E6B4A  mov         dword ptr [ebp-0E0h],esi  
002E6B50  mov         esi,dword ptr [p]  
002E6B53  push        esi  
002E6B54  mov         esi,esp  
002E6B56  push        offset std::endl<char,std::char_traits<char> > (02E1410h)  
002E6B5B  mov         dword ptr [ebp-0E4h],edi  
002E6B61  mov         edi,esp  
002E6B63  mov         dword ptr [ebp-0E8h],ebx  
002E6B69  lea         ebx,[a]  
002E6B6C  push        ebx  
002E6B6D  mov         ebx,esp  
002E6B6F  push        offset std::endl<char,std::char_traits<char> > (02E1410h)  
002E6B74  mov         dword ptr [ebp-0ECh],eax  
002E6B7A  mov         eax,esp  
002E6B7C  push        1  
002E6B7E  mov         dword ptr [ebp-0F0h],ecx  
002E6B84  mov         ecx,dword ptr [_imp_?cout@std@@3V?$basic_ostream@DU?$char_traits@D@std@@@1@A (02EC098h)]  
002E6B8A  mov         dword ptr [ebp-0F4h],eax  
002E6B90  mov         dword ptr [ebp-0F8h],edx  
002E6B96  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (02EC09Ch)]  
002E6B9C  mov         ecx,dword ptr [ebp-0F4h]  
002E6BA2  cmp         ecx,esp  
002E6BA4  call        __RTC_CheckEsp (02E1276h)  
002E6BA9  mov         ecx,eax  
002E6BAB  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (02EC0ACh)]  
002E6BB1  cmp         ebx,esp  
002E6BB3  call        __RTC_CheckEsp (02E1276h)  
002E6BB8  mov         ecx,eax  
002E6BBA  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (02EC0A8h)]  
002E6BC0  cmp         edi,esp  
002E6BC2  call        __RTC_CheckEsp (02E1276h)  
002E6BC7  mov         ecx,eax  
002E6BC9  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (02EC0ACh)]  

在vs2017下这一句的反汇编结果,可以看到,这几个地方直接push的是1,也就是直接把字面值给push进去了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2019-3-14 15:00:43 | 显示全部楼层
这个是编译器的问题吗?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-3-14 15:02:51 | 显示全部楼层
我记得是因为现在很多编译器在编译时会将能够在编译期间就能确定的常量值替换为相应的字面值,作为代码优化的一部分;
但这个是编译器相关的,不同的编译器可能有不同的做法
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-3-14 15:06:25 | 显示全部楼层
Croper 发表于 2019-3-14 15:02
我记得是因为现在很多编译器在编译时会将能够在编译期间就能确定的常量值替换为相应的字面值,作为代码优化 ...

感觉常量编译器相当于生成了字典吧,他根本不是通过地址得到常量的值的,而是仅仅通过变量名
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-3-14 15:07:25 | 显示全部楼层
      我想这样来理解,a 是只读变量,虽然可以通过指针修改这个变量所占用的内存,但是,如果通过 a 来访问这个变量,它仍然还是
1,因为这个变量是只读的,如果通过指针来访问,就会正常访问到你所修改过的值。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-3-14 15:12:22 | 显示全部楼层
jackz007 发表于 2019-3-14 15:07
我想这样来理解,a 是只读变量,虽然可以通过指针修改这个变量所占用的内存,但是,如果通过 a 来访 ...

感觉编译器是把常量转化为宏定义了吧
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-3-14 15:12:55 | 显示全部楼层
lcl1026504480 发表于 2019-3-14 15:12
感觉编译器是把常量转化为宏定义了吧

可以反汇编看一看的
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-3-14 15:18:13 | 显示全部楼层    本楼为最佳答案   
        cout << a << endl << &a << endl << p << endl << *p << endl << *(&a) << endl;
002E6B27  mov         esi,esp  
002E6B29  push        offset std::endl<char,std::char_traits<char> > (02E1410h)  
002E6B2E  mov         edi,esp  
002E6B30  push        1  
002E6B32  mov         ebx,esp  
002E6B34  push        offset std::endl<char,std::char_traits<char> > (02E1410h)  
002E6B39  mov         eax,esp  
002E6B3B  mov         ecx,dword ptr [p]  
002E6B3E  mov         edx,dword ptr [ecx]  
002E6B40  push        edx  
002E6B41  mov         ecx,esp  
002E6B43  push        offset std::endl<char,std::char_traits<char> > (02E1410h)  
002E6B48  mov         edx,esp  
002E6B4A  mov         dword ptr [ebp-0E0h],esi  
002E6B50  mov         esi,dword ptr [p]  
002E6B53  push        esi  
002E6B54  mov         esi,esp  
002E6B56  push        offset std::endl<char,std::char_traits<char> > (02E1410h)  
002E6B5B  mov         dword ptr [ebp-0E4h],edi  
002E6B61  mov         edi,esp  
002E6B63  mov         dword ptr [ebp-0E8h],ebx  
002E6B69  lea         ebx,[a]  
002E6B6C  push        ebx  
002E6B6D  mov         ebx,esp  
002E6B6F  push        offset std::endl<char,std::char_traits<char> > (02E1410h)  
002E6B74  mov         dword ptr [ebp-0ECh],eax  
002E6B7A  mov         eax,esp  
002E6B7C  push        1  
002E6B7E  mov         dword ptr [ebp-0F0h],ecx  
002E6B84  mov         ecx,dword ptr [_imp_?cout@std@@3V?$basic_ostream@DU?$char_traits@D@std@@@1@A (02EC098h)]  
002E6B8A  mov         dword ptr [ebp-0F4h],eax  
002E6B90  mov         dword ptr [ebp-0F8h],edx  
002E6B96  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (02EC09Ch)]  
002E6B9C  mov         ecx,dword ptr [ebp-0F4h]  
002E6BA2  cmp         ecx,esp  
002E6BA4  call        __RTC_CheckEsp (02E1276h)  
002E6BA9  mov         ecx,eax  
002E6BAB  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (02EC0ACh)]  
002E6BB1  cmp         ebx,esp  
002E6BB3  call        __RTC_CheckEsp (02E1276h)  
002E6BB8  mov         ecx,eax  
002E6BBA  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (02EC0A8h)]  
002E6BC0  cmp         edi,esp  
002E6BC2  call        __RTC_CheckEsp (02E1276h)  
002E6BC7  mov         ecx,eax  
002E6BC9  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (02EC0ACh)]  

在vs2017下这一句的反汇编结果,可以看到,这几个地方直接push的是1,也就是直接把字面值给push进去了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-3-14 15:20:10 | 显示全部楼层
lcl1026504480 发表于 2019-3-14 15:12
感觉编译器是把常量转化为宏定义了吧

        可是 & a 的确取到了变量地址,这样来看,应该不是宏定义。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-10-3 10:46

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表