在C语言中,const是如何保证变量不被修改的?大神给你答案

2022-12-31 0 306

在C词汇中,$const$是怎样确保表达式不被修正的?

他们能想不到三种形式:

在C语言中,const是如何保证变量不被修改的?大神给你答案

第二种,由校对器来制止 修正$const$表达式的句子,让此种流程无法透过校对;

第三种,由作业系统来制止,即把$const$ 的内存地址出访职权记号为“黎贞”,除非运转中的流程企图修正它,就会造成极度,中止民主化。

下面想不到的这三种形式,都能达至让某一表达式的值不被修正的目地,所以到底是哪一类呢?他们写三个范例上看细看。

先上看三个单纯的范例,示例const.c:

在C语言中,const是如何保证变量不被修改的?大神给你答案

校对,会接到三个 warning:

$ gcc -o const1 const1.cconst.c:Infunction‘main’:const.c:7:12: warning:initializationdiscards ‘const’ qualifier from pointer targettype[-Wdiscarded-qualifiers] int *p=&a;

忽略之,运转流程:

在C语言中,const是如何保证变量不被修改的?大神给你答案

运转出错了,报错是“segmentation fault”,即“段错误”,它是在提醒他们,流程中用错误的职权出访了内存某区域。这说明,作业系统把表达式$a$加载到了一段黎贞内存区域之中,因此对该区域地址的写操作将引发极度,这是由作业系统的内存保护机制决定的。

也就是说,在这段流程里,$const$的黎贞属性是由作业系统来实现的,而不是由校对器来实现的(校对器只抛出了warning,并没有制止校对透过)。

这对吗?不完全对,他们上看另三个范例,示例const2.c:

在C语言中,const是如何保证变量不被修改的?大神给你答案

校对,还是接到同样的warning:

$ gcc -o const2 const2.cconst.c:Infunction‘main’:const.c:6:12: warning:initializationdiscards ‘const’ qualifier from pointer targettype[-Wdiscarded-qualifiers] int *p=&a;

忽略之,运转流程:

在C语言中,const是如何保证变量不被修改的?大神给你答案

咦?怎么成功运转了,而且$a$的值还被顺利修正了?

结合以上三个范例,他们能得出以下结论:

$const$只是C词汇中的一种对表达式的修饰符,范例中的$a$,与其说是“常量”,不如说是“不打算修正的表达式”。 它只是语法上的一类声明 ,它的作用就是告诉校对器“我不想修正它”,因此校对器会从语法上检查流程中是否有修正它的句子(例如“a=1;”),除非发现此种“违背初衷”的句子,就会报错制止你。

然而,校对器所制止的仅仅是对$a$这个符号 对应值的修正而已,却并不制止对这个地址的值的修正,示例“const2.c”之所以能顺利透过编译且正常运转,就是因为它利用三个名字不叫$a$的指针 指向它,从而绕过了校对器的语法检查。

打个比方,周树人的笔名叫鲁迅,警察只知道要抓鲁迅,这时候他就能用一句“你们抓鲁迅跟我周树人有什么关系?”来骗过他们。

从这个角度来说,$const$的作用是靠校对器仅仅从语法检查来实现的,因此存在运转时的漏洞。

在C语言中,const是如何保证变量不被修改的?大神给你答案

所以为什么“const1.c”就无法正常运转呢?

仔细看这三个源流程,区别仅仅在于,在const1.c中,$a$被声明为全局表达式 ,而在const2.c中,它被声明为main函数中的三个局部表达式。全局表达式与局部表达式的区别在于,前者会在流程开始运转之前就被加载,加载后会一直留在内存中,且加载的位置在数据区,直到流程退出;后者只有在运转到它时才会被加载,且加载的位置是运转时的栈帧,除非超出作用于就会被回收。

因此,校对器会对被声明为全局表达式的$const\ int\ a$进行优化 ,把它放到黎贞内存区内,这一内存区的职权是$read\ only$,职权信息由作业系统所维护的段表来保存,流程每出访某地址时,作业系统都会检测其出访职权是否合法。const2.c中企图用“写”的形式来出访“黎贞”的段,自然会报出“segment fault”的错了。

从这个角度来说,当$a$是全局表达式时,校对器把原本只是“不打算修正的表达式”优化成了“真正的常量”,然后交给作业系统去维持其不变属性。

在C语言中,const是如何保证变量不被修改的?大神给你答案

综上所述,C的初衷只是让校对器去确保$const$的不变属性,这一属性有漏洞(能用指针去骗过校对器修正它),所以当const修饰的对象是全局表达式时(全局表达式很重要,因为很多示例都要出访它,牵一发而动全身,所以不应轻易更改),校对器知道自己的能力有限,只能管得了校对,管不了运转时怎样,所以优化了句子把它编程真正的常量,让作业系统的内存保护功能来履行这一职责。

这一优化,并不是C规定的,而是校对器厂商出于实际应用的考虑作出的选择。

欢迎交流。

PS:另外对于学习编程或者正在工作的朋友,如果你想更好的提升你的编程能力乃至转行,弯道超车,快人一步!笔者这里或许能帮到你~

编程学习书籍分享:

在C语言中,const是如何保证变量不被修改的?大神给你答案

编程学习视频分享:

在C语言中,const是如何保证变量不被修改的?大神给你答案

分享(源码、项目实战视频、项目笔记,基础入门教程)

欢迎转行和学习编程的伙伴,利用更多的资料学习成长比自己琢磨更快哦!

点击下方【了解更多

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务