C和C++中const变量内存分配问题详解

一、C语言中的const变量

  1. 在c语言中,以const关键字声明的对象,其值不能通过赋值或者递增,递减来修改,所以要一开始初始化变量
  2. const修饰的变量不是常量,本质上是 常变量

const int tmp = 10;//这里不管tmp是全局的,还是局部的
int arry[tmp] = {1, 2, 3};//都会报错,“表达式必须包含常量值”

  1. const修饰的全局变量,在常量区(.rodata段)分配内存空间,不能通过变量地址来修改值;const修饰的局部变量在栈区分配内存空间,可以通过变量地址来修改值
  2. c语言的const修饰全局变量 默认是外部链接的(外部链接:其他源文件 可以使用)。
    //c语言的const修饰全局变量 默认是(外部链接的)
    //外部链接:其他源文件 可以使用
//fun.c
    const int num = 100;//只读的全局变量 内存放在文字常量区(内存空间只读)
   
//main.c
//对fun.c中的num进行声明(不要赋值)
    extern const int num;
    void test03()
    {
        printf("num = %d\n",num);
        //num = 200;//err num只读
   
        //C语言中const 修饰变量名 说明变量名为只读(用户不能通过变量名data进行赋值)
        const int data = 100;//局部只读变量 内存在栈区(内存可读可写)
        //data = 200;//err
     
        printf("data = %d\n",data);
        //但是:如果知道data的地址 可以通过地址间接的修改data所对应空间的内容
        int *p = (int *)&data;
        *p = 2000;
        printf("data = %d\n",data);//ok 200
    }

二、C++中的const变量

const 在C++中是用来修饰内置类型变量,自定义对象,成员函数,返回值,函数参数。

1.const全局变量,或者static,extern 关键字

此时该常量是存放在.rodata段的—Read Only Data也就是常量区,是无法通过取地址方式去修改的,修改内容会报段错误(gcc++编译器:Segmentation fault(core dumped)).

例如:
extern const int i=10
static const int i=10

const修饰的全局变量默认是内部链接,即只在当前源文件有效 不能直接用于其他源文件,如果必须用在其他源文件 使用只读的全局变量 必须加extern将变量转换成外部链接。

2.const局部变量内存分配

在这里插入图片描述

  • c++中 对于基础类型(整数,浮点数,字符) 系统不会给const变量开辟空间 ,会将其放到符号表中;
  • c++中当 对const变量取地址的时候 系统就会给它开辟空间;
  • 当用变量给const变量赋值时,系统直接为其开辟空间 而不会把它放入符号表中;(下面示例程序中的const变量a)
  • const 自定义数据类型(结构体、对象) 和数组系统会分配空间;

fun.cpp

    //const修饰的全局变量 默认是内部链接(只在当前源文件有效 不能直接用于其他源文件)
    //const int num = 100;
    //如果必须用在其他源文件 使用只读的全局变量 必须加extern将num转换成外部链接
    extern const int num = 100;

main.cpp

//声明
    extern const int num;
    struct Person
    {
        int num;
        char name[32];
    };
    void test04()
    {
        cout<<"全局num = "<<num<<endl;//err 不识别num
     
        //1、c++中 对于基础类型 系统不会给data开辟空间 data放到符号表中
        const int data = 10;
        //data = 100;//err 只读
        cout<<"data = "<<data<<endl;
        //2、c++中当 对data 取地址的时候 系统就会给data开辟空间
        int *p = (int *)&data;
        *p = 2000;
        cout<<"*p = "<<*p<<endl;//空间内容修改成功 2000
     
        cout<<"data = "<<data<<endl;//data 还是10为啥?
     
        //2、当以变量的形式 初始化 const修饰的变量 系统会为其开辟空间
        int b = 200;
        const int a= b;//系统直接为a开辟空间 而不会把a放入符号表中
        p = (int *)&a;
        *p = 3000;
        cout<<"*p = "<<*p <<endl;//3000
        cout<<"a = "<<a <<endl;//3000
     
        //3、const 自定义数据类型(结构体、对象) 系统会分配空间
        const Person per = {100,"lucy"};
        //per.num = 1000;//err
        cout<<"num = "<<per.num<<", name = "<<per.name<<endl;//100 lucy
        Person *p1 = (Person *)&per;
        p1->num = 2000;
        cout<<"num = "<<per.num<<", name = "<<per.name<<endl;//2000 lucy
    }

三、关于C++中const变量内存分配的争议

关于c++中const局部变量在程序运行时是否分配了内存有两种观点:

实践出真知,我们验证下:
实验环境:win10,vs2019(在Linux,g++请自行验证)

  1. 在release模式下,程序中没有‘&’取地址符:
    直接查看tmp变量的地址,显示“无法计算表达式”,说明没有分配内存;
    在这里插入图片描述

  2. 在release模式下,程序中有‘&’取地址符:
    调试到第六行tmp的地址值为0x007DFC08,该地址中的值为11211500(0x00ab12ec),说明分配了4个字节的内存,里面的值是乱码值,不是10,不是10,不是10

在这里插入图片描述
调试到第九行,tmp的地址值为0x007DFC08,该地址中的值为10;
在这里插入图片描述
调式到第11行,tmp的地址值为0x007DFC08,该地址中的值为20;但显示出的tmp:10,说明显示的是符号表中的值,而不是0x007DFC08地址中的。
在这里插入图片描述

  1. Debug模式下,没有‘&’取地址符:
    分配了内存
    在这里插入图片描述
    参考文章:细谈c++的const
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值