C语言学习过程中的问题之const



一、问题描述:   

#include<stdio.h>
int main()
{
    const int a = 10;
    int *p = &a;
    *p = 20;
    printf("a = %d *p = %d\n",a,*p)
}

      上面这段代码,输出为*p = 20,a = 10,可是从代码中我们可以明显看到*p指向的地址和变量a的地址是一样的,可是当我们给指针p所指向的内存地址赋值也就是*p = 20以后,相同地址的变量a的值却不变,到底是为什么呢?

二、解决过程

    上网查询资料后,发现是编译器自动优化的,用下面这段代码就可以:

#include<stdio.h>
int main()
{
     volatile const int a = 10;
    int *p = &a;
    *p = 20;
    printf("a = %d *p = %d\n",a,*p)
}

     上面这段代码的输出为:a = 20,*p = 20;果然用了volatile跳过编译器的自动优化后,就可以用指针改变const只读变量的值了。可是编译器是怎么优化的呢,我们知道,在内存中,给运行的程序按地址由低到高划分了五个区:代码区、常量区、静态区、栈区和堆区。也就是说,程序运行的时候,内存中是有存储常量的区域的,那么这里编译器是如何让cpu可以不从内存中拿数据的呢。

     近来正在阅读《汇编语言(王爽)》和《计算机组成与设计  硬件/软件接口》,原来cpu只会去操作寄存器中的值,而不是直接从内存中取值,要操作内存(存储器)中数据,只会通过立即数取值、寄存器取值、基址取值、pc相对寻址、伪直接寻址,将内存中的数据读入寄存器后再进行相应的操作。

     现在的cpu基本有两类寄存器,保留的(程序运行时,可以将数据保留在寄存器中)和不保留的(在程序运行的过程中,和内存不断交换数据)。保留的包括:全局指针,栈指针,帧指针,返回地址;不保留的包括:临时变量、参数、表达式求值和计算结果。

      回到刚才的问题,const是将变量a定义为只读,那么编译器在编译(形成汇编语言)的时候就会将变量a用初始化的常量来代替,比如: 用mov R1 $10来代替move R1 (R2),R2中存储的是变量a的地址。这样R1这个寄存器是保留的,程序运行的过程中,不释放,这样就不用去内存中读取,直接从寄存器中取出。

      同时给变量a一个块内存(在栈中)地址,在程序运行的时候,a其实是和a的那块内存是分开的,用变量a的时候用的是寄存器的数据,而不是内存中的数据,这样改变*q中的数据只是改变了内存中的数据,跟程序运行时a的值根本没有关系。

转载于:https://my.oschina.net/u/2535052/blog/536931

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值