前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C++中Const常量机制分析

C++中Const常量机制分析

原创
作者头像
洛杉矶
修改2020-10-22 17:42:46
2.2K0
修改2020-10-22 17:42:46
举报
文章被收录于专栏:技术最杂谈技术最杂谈

const常量机制分析

const为C/C++常用的修饰符,表示该变量是一个常量,不可被修改等含义。那么在实际使用中会存在如下疑问:

1,const修饰的变量是否真的不可修改?

2,如果被修改,会出现什么问题?

3,C和C++中实现机制一样吗?

4,对于内置类型和自定义类型数据,const实现原理一样吗?

5,为什么const变量可以被定义在.h头文件中?

问题1, const修饰的变量是否真的不可修改?

1.1 编译器保证了const修饰的变量不能被修改或者重新赋值。

const int var = 10;

var = 20;//编译报错,不能被修改

1.2 通过指针修改const变量。

const int var = 10;

int* ptr_const = (int*) (&var);

ptr_const = 20;

1) 局部const变量,对于C++程序,该变量地址中的值可以被修改,但是对其的修改不会影响变量实际被引用地方的值。对于c程序,该变量可被修改,且变量使用地方也会受到影响。

对于C++程序:

int main(int argc,char**argv)

{

const int var = 10;

int* ptr_const = (int*) (&var);

printf("ptr_const= %x, var= %x\n", ptr_const, &var);

printf("var= %d, *ptr_const=%d\n", var, *ptr_const);

*ptr_const = 20;

printf("var= %d, *ptr_const=%d\n", var, *ptr_const);

printf("ptr_const= %x, var= %x\n", ptr_const, &var);

可见,对变量地址的值进行修改后,var使用的值也变化,为最新的值。

2)对于全局变量,静态局部变量,全局静态变量都不能被修改,否则会core。

代码:

const int var = 10;

int main(int argc,char**argv)

{

int* ptr_const = (int*) (&var);

printf("ptr_const= %x, var= %x\n", ptr_const, &var);

printf("var= %d, *ptr_const=%d\n", var, *ptr_const);

*ptr_const = 20;

printf("var= %d, *ptr_const=%d\n", var, *ptr_const);

printf("ptr_const= %x, var= %x\n", ptr_const, &var);

return 0 ;

}

运行结果:

可以看到var变量的地址在0x4008c8。

我们来看看0x4008c8是位于程序的的哪个段。

执行命令

readelf -s msgq

看到符号var地址和程序输出的完全一致。其对应的Ndx下标为14,表明该变量存储在msgq文件中的下标为14的段。

执行命令

readelf -S msgq

可见,对变量地址的值进行修改后,var使用的值也变化,为最新的值。

2)对于全局变量,静态局部变量,全局静态变量都不能被修改,否则会core。

代码:

const int var = 10;

int main(int argc,char**argv)

{

int* ptr_const = (int*) (&var);

printf("ptr_const= %x, var= %x\n", ptr_const, &var);

printf("var= %d, *ptr_const=%d\n", var, *ptr_const);

*ptr_const = 20;

printf("var= %d, *ptr_const=%d\n", var, *ptr_const);

printf("ptr_const= %x, var= %x\n", ptr_const, &var);

return 0 ;

}

运行结果:

可以看到var变量的地址在0x4008c8。

我们来看看0x4008c8是位于程序的的哪个段。

执行命令

readelf -s msgq

看到符号var地址和程序输出的完全一致。其对应的Ndx下标为14,表明该变量存储在msgq文件中的下标为14的段。

执行命令

readelf -S msgq

可以看到位于只读数据段.rodata,当然程序不允许修改该地址内的数据,所以会core。

结论:

对于全局变量,局部静态变量,全局静态变量,存储在程序的只读数据段,不能被修改。

2,如果const变量被修改,会出现什么问题?

在问题1中已经得到了结论和验证。

3,C和C++中实现机制一样吗?

3.1不同点:

对于局部const变量,C++在变量具体使用地方通过常量替换实现。C语言中表示只读的变量。

3.2 相同点:

都不能对只读数据段的常量进行修改。如:全局变量,静态局部数据变量,全局静态变量。

4,对于内置类型和自定义类型数据,const实现原理一样吗?

4.1局部变量

内置类型和自定义类型完全一样,都没有分配存储空间。运行时在栈空间存储,每次运行地址不定,可以通过指针修改其值。

代码

struct test

{

int var;

test(int x)

{

var = 30*40;

}

};

int main(int argc,char**argv)

{

const test testObj(5);

int* ptr_Obj = (int*) (&testObj.var);

printf("ptr_const= %x, var= %x\n", ptr_Obj, &testObj.var);

printf("ptr_const= %d, var= %d\n", *ptr_Obj, testObj.var);

*ptr_Obj = 40;

printf("ptr_const= %d, var= %d\n", *ptr_Obj, testObj.var);

}

运行结果:

4.2全局变量或者静态变量(全局和局部)

自定义类型const变量存分配空间,存储在bss段,且可以被修改。

内置类型const变量分配空间,存储在只读数据段.rodata,不能被修改。

代码

struct test

{

int var;

test(int x)

{

var = 30*40;

}

};

static const test testObj(3);

int main(int argc,char**argv)

{

int* ptr_Obj = (int*) (&testObj.var);

printf("ptr_const= %x, var= %x\n", ptr_Obj, &testObj.var);

printf("ptr_const= %d, var= %d\n", *ptr_Obj, testObj.var);

*ptr_Obj = 40;

printf("ptr_const= %d, var= %d\n", *ptr_Obj, testObj.var);

}

结果:

查看符号表

readelf -s msgq

查看段表

可以看到位于.bss段。

5,为什么const变量可以被定义在.h头文件中?

我们都知道,.h头文件中不能有定义。其中const变量,类和模版是特例。

5.1 在.h中声明const变量

在头文件中extern const int var;//声明

在cpp文件中只能定义一次,否则会出现重定义。

因为这种情况生成的.o文件符号表存在var。

5.2在.h中定义const变量

在头文件中定义const变量

const int var =10;

在多个cpp文件中引用该文件。并把cpp对应生成的.o文件链接为可执行程序。

可以正常编译链接,不会报错。

会对该const变量分配空间,且被重复存储在不同只读数据段。重复次数和引用该.h文件的cpp生成的.o文件个数一致。且各存储地址不一样,都不能通过指针被修改。

查看符号表。

可以看到存在两个var符号,地址不同。

运行结果

各cpp文件读取对应的只读数据段的数据,互不影响。

特别注意点:

对于头文件定义字符串指针常量的正确定义如下:

const char * const constCharPtr="hello const";

表示指针常量,则可以放在头文件。

而不是常量指针,下面这句在头文件中,如果被多个cpp包含。则会出现重定义。

const char *constCharPtr="hello const";

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
对象存储
对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
http://www.vxiaotou.com