最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

在C語言中,const是如何保證變量不被修改的?大神給你答案

2021-04-08 18:37 作者:C語言編程__Plus  | 我要投稿

在C語言中,$const$是如何保證變量不被修改的?

我們可以想到兩種方式:


第一種,由編譯器來阻止?修改$const$變量的語句,讓這種程序不能通過編譯;

第二種,由操作系統(tǒng)來阻止?,即把$const$ 的內(nèi)存地址訪問權(quán)限標(biāo)記為“只讀”,一旦運行中的程序試圖修改它,就會產(chǎn)生異常,終止進程。

上面想到的這兩種方式,都能達(dá)到讓某一變量的值不被修改的目的,那么究竟是哪一種呢?我們寫兩個例子來看一看。

先來看一個簡單的例子,源文件const.c:


編譯,會收到一個 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;

忽略之,運行程序:


運行出錯了,報錯是“segmentation fault”,即“段錯誤”,它是在提醒我們,程序中用錯誤的權(quán)限訪問了內(nèi)存某區(qū)域。這說明,操作系統(tǒng)把變量$a$加載到了一段只讀內(nèi)存區(qū)域之中,因此對該區(qū)域地址的寫操作將引發(fā)異常,這是由操作系統(tǒng)的內(nèi)存保護機制決定的。

也就是說,在這段程序里,$const$的只讀屬性是由操作系統(tǒng)來實現(xiàn)的,而不是由編譯器來實現(xiàn)的(編譯器只拋出了warning,并沒有阻止編譯通過)。

這對嗎?不完全對,我們來看另一個例子,源文件const2.c:


編譯,還是收到同樣的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;

忽略之,運行程序:


咦?怎么成功運行了,而且$a$的值還被順利修改了?

結(jié)合以上兩個例子,我們可以得出以下結(jié)論:

$const$只是C語言中的一種對變量的修飾符,例子中的$a$,與其說是“常量”,不如說是“不打算修改的變量”。?它只是語法上的一種聲明?,它的作用就是告訴編譯器“我不想修改它”,因此編譯器會從語法上檢查程序中是否有修改它的語句?(例如“a=1;”),一旦發(fā)現(xiàn)這種“違背初衷”的語句,就會報錯阻止你。

然而,編譯器所阻止的僅僅是對$a$這個符號?對應(yīng)值的修改而已,卻并不阻止對這個地址的值的修改?,源文件“const2.c”之所以能順利通過編譯且正常運行,就是因為它利用一個名字不叫$a$的指針?指向它,從而繞過了編譯器的語法檢查。

打個比方,周樹人的筆名叫魯迅,警察只知道要抓魯迅,這時候他就可以用一句“你們抓魯迅跟我周樹人有什么關(guān)系??”來騙過他們。

從這個角度來說,$const$的作用是靠編譯器僅僅從語法檢查來實現(xiàn)的,因此存在運行時的漏洞。


那么為什么“const1.c”就不能正常運行呢?

仔細(xì)看這兩個源程序,區(qū)別僅僅在于,在const1.c中,$a$被聲明為全局變量?,而在const2.c中,它被聲明為main函數(shù)中的一個局部變量?。全局變量與局部變量的區(qū)別在于,前者會在程序開始運行之前就被加載,加載后會一直留在內(nèi)存中,且加載的位置在數(shù)據(jù)區(qū),直到程序退出;后者只有在運行到它時才會被加載,且加載的位置是運行時的棧幀,一旦超出作用于就會被回收。

因此,編譯器會對被聲明為全局變量的$const\ int\ a$進行優(yōu)化?,把它放到只讀內(nèi)存區(qū)內(nèi)?,這一內(nèi)存區(qū)的權(quán)限是$read\ only$,權(quán)限信息由操作系統(tǒng)所維護的段表來保存,程序每訪問某地址時,操作系統(tǒng)都會檢測其訪問權(quán)限是否合法。const2.c中企圖用“寫”的方式來訪問“只讀”的段,自然會報出“segment fault"的錯了。

從這個角度來說,當(dāng)$a$是全局變量時,編譯器把原本只是“不打算修改的變量”優(yōu)化成了“真正的常量”,然后交給操作系統(tǒng)去維持其不變屬性。


綜上所述,C的初衷只是讓編譯器去保證$const$的不變屬性,這一屬性有漏洞(可以用指針去騙過編譯器修改它),所以當(dāng)const修飾的對象是全局變量時(全局變量很重要,因為很多源文件都要訪問它,牽一發(fā)而動全身,所以不應(yīng)輕易更改),編譯器知道自己的能力有限,只能管得了編譯,管不了運行時如何,所以優(yōu)化了語句把它編程真正的常量,讓操作系統(tǒng)的內(nèi)存保護功能來履行這一職責(zé)。

這一優(yōu)化,并不是C規(guī)定的,而是編譯器廠商出于實際應(yīng)用的考慮作出的選擇。

歡迎交流。

PS:另外對于學(xué)習(xí)編程或者正在工作的朋友,如果你想更好的提升你的編程能力乃至轉(zhuǎn)行,彎道超車,快人一步!筆者這里或許可以幫到你~

C語言C++編程學(xué)習(xí)交流圈子,【點擊進入】微信公眾號:C語言編程學(xué)習(xí)基地

分享(源碼、項目實戰(zhàn)視頻、項目筆記,基礎(chǔ)入門教程)

歡迎轉(zhuǎn)行和學(xué)習(xí)編程的伙伴,利用更多的資料學(xué)習(xí)成長比自己琢磨更快哦!

編程學(xué)習(xí)書籍分享:

編程學(xué)習(xí)視頻分享:


在C語言中,const是如何保證變量不被修改的?大神給你答案的評論 (共 條)

分享到微博請遵守國家法律
宜州市| 蓬莱市| 博客| 林周县| 和政县| 维西| 黄陵县| 玉树县| 荥经县| 和平县| 临武县| 新昌县| 巨野县| 尤溪县| 万年县| 江西省| 寿光市| 德化县| 长丰县| 定襄县| 洛宁县| 云林县| 吉安市| 二连浩特市| 江华| 喀什市| 三门峡市| 五寨县| 舒城县| 榆社县| 建瓯市| 山丹县| 峨边| 凤庆县| 江达县| 深水埗区| 拜泉县| 株洲市| 宜州市| 大同市| 翼城县|