在C語(yǔ)言中,請(qǐng)記住要初始化局部變量!

        在C語(yǔ)言中,有多少個(gè)未初始化的局部變量?答案通常是:與編譯器有關(guān)。

        可以但不保證初始化為0。

        不確定。

        簡(jiǎn)而言之,它們都是嚴(yán)肅的形而上學(xué)的答案,這很煩人。

        但是,當(dāng)有人為您談?wù)摼幾g器,C庫(kù)和處理器體系結(jié)構(gòu)時(shí),卻無(wú)法為您提供重現(xiàn)該問(wèn)題的真實(shí)場(chǎng)景,那么這個(gè)人很可能是胡說(shuō)八道。

        實(shí)際上,這個(gè)問(wèn)題本身是一個(gè)錯(cuò)誤的問(wèn)題。

        如果您能說(shuō)100,000個(gè)單詞,我們只需要能夠確定其在特定情況下的特定行為。

        當(dāng)然,這需要設(shè)計(jì)一個(gè)相對(duì)可行的實(shí)驗(yàn)。

        在演示實(shí)際代碼的行為之前,讓我給出一些知識(shí)。

        CPU無(wú)法識(shí)別變量,更不用說(shuō)變量名了。

        CPU只會(huì)從特定的存儲(chǔ)位置獲取值,或者將值存儲(chǔ)在特定的存儲(chǔ)位置,因此當(dāng)被問(wèn)到變量的值是什么時(shí),有必要知道該變量的值存儲(chǔ)在哪里。

        考慮以下代碼:#include void func1(){int a; printf(“ func1:%d ”,a); a = 12345;} void func2(){int b; printf(“ func2:%d ”,b);} void func4(){int d; printf(“ func3:%d ”,d);} void func3(){int c; printf(“ func3:%d " c); c = 54321; func4();} void test_call(){func3();} int main(int argc,char ** argv){func1(); func2(); test_call();}我們從func1到func4一共有4個(gè)函數(shù),并且內(nèi)部有一個(gè)未初始化的局部變量。

        它們的價(jià)值是什么?對(duì)于這種局部變量,其值取決于:變量在堆棧中的位置。

        該變量對(duì)應(yīng)于堆棧位置是否已存儲(chǔ)過(guò)?如您所見(jiàn),上面的第一點(diǎn)標(biāo)記了一個(gè)內(nèi)存位置,第二點(diǎn)是代碼的行為,即只要有存儲(chǔ)對(duì)應(yīng)位置的代碼,以及后面的代碼(如果沒(méi)有復(fù)位值)位置的位置,位置將在存儲(chǔ)后保留原始值。

        驗(yàn)證非常簡(jiǎn)單,請(qǐng)嘗試:[root @ localhost test]#./a.outfunc1:0func2:12345func3:0func3:0根據(jù)函數(shù)調(diào)用堆??蚣埽琭unc1的局部變量a和局部變量的變化而定func2的變量b顯然位于同一位置。

        調(diào)用func1時(shí),這是一個(gè)新的內(nèi)存(也許在進(jìn)入main之后,堆棧幀到達(dá)了該位置之后),a的值取決于在此位置被調(diào)用到內(nèi)存中的頁(yè)面的相應(yīng)偏移量的初始值。

        在操作系統(tǒng)上:將操作系統(tǒng)分配給程序頁(yè)面時(shí),操作系統(tǒng)可能會(huì)將頁(yè)面清除為零頁(yè)面。

        堆棧分配不會(huì)涉及C庫(kù)。

        顯然,這里不涉及C庫(kù)的行為,但是malloc分配的內(nèi)存涉及C庫(kù)。

        打印的結(jié)果顯示a的值為0,我們認(rèn)為操作系統(tǒng)已向應(yīng)用程序返回了零頁(yè)。

        接下來(lái),該函數(shù)將其分配給func1中的12345后返回。

        當(dāng)下一次調(diào)用func2時(shí),將在以前退出func1的堆??蚣芪恢弥亟ǘ褩?蚣埽⑶蚁鄳?yīng)位置仍為12345。

        在執(zhí)行func1代碼指令0的ret操作后,我沒(méi)有看到堆棧清除。

        考慮因素,不應(yīng)有此類(lèi)說(shuō)明。

        查看test_call函數(shù),很明顯,func3和func4不是使用同一堆棧幀來(lái)調(diào)用的,因此即使將func3中的c分配給了54321,也不會(huì)影響func4在堆棧幀上方的值d 。

        因此,c和d的初始值保持為0.然后,在指令級(jí)初始化局部變量而不初始化局部變量的區(qū)別是什么?這很簡(jiǎn)單,只需用自己的眼睛看一下即可。

        首先看一下未初始化的局部變量的func1:// int a; 00000000004005ad:4005ad:55 push%rbp 4005ae:48 89 e5 mov%rsp,%rbp 4005b1:48 83 ec 10 sub $ 0 x10,%rsp 4005b5:8b 45 fc mov -0x4(%rbp),%eax 4005b8:89 c6 mov%eax,%esi 4005ba:bf 90 07 40 00 mov $ 0x400790,%edi 4005bf:b8 00 00 00 00 mov $ 0x0,%eax 4005c4: e8 b7 fe ff ff callq 400480 4005c9:c7 45 fc 39 30 00 00 movl $ 0x3039,-0x4(%rbp)4005d0:c9 Leaveq 4005d1:c3 retq查看局部變量a的初始化2222版本:// int a = 2222; 00000000004005ad:4005ad:55 push%rbp 4005ae:48 89 e5 mov%rsp,%rbp 4005b1:48 83 ec 10 sub $ 0x10,%rsp 4005b5:c7 45 fc 00 00 00 00 movl $ 0x0,-0x4( %rbp)4005bc:8b 45 fc mov -0x4(%rbp),%eax 4005bf:89 c6 mov%eax,%esi 4005c1:bf 90 07 40 00 mov $ 0x400790,%edi 4005c6:b8 00 00 00 00 mov $ 0 x0,%eax 4005cb:e8 b0 fe ff ff callq 400480 4005d0:c7 45 fc 39 30 00 00 movl $ 0x3039,-0x 4(%rbp)4005d7:c9 Leaveq 4005d8:c3 retq僅缺少一條指令:4005b5: c7 45 fc 00 00 00 00 movl $ 0x0,-0x4(%rbp)初始化操作由實(shí)際指令完成

        產(chǎn)品知識(shí)/行業(yè)、品牌資訊

        行業(yè)、品牌資訊


        主站蜘蛛池模板: 成人免费av一区二区三区| 久久精品国产亚洲一区二区三区| 亚洲Aⅴ无码一区二区二三区软件| 亚洲国产成人精品久久久国产成人一区二区三区综 | 中文字幕一区在线播放| 亚洲人成网站18禁止一区| 国产AV国片精品一区二区| 亚洲精品一区二区三区四区乱码| 国产成人精品一区二区三在线观看| 精品一区二区三区波多野结衣| 国产成人综合精品一区| 天天综合色一区二区三区| 国产午夜精品一区二区三区漫画| 亚洲欧洲一区二区| 亚洲中文字幕无码一区| 农村人乱弄一区二区| 国产成人无码aa精品一区| 国产乱人伦精品一区二区在线观看| 一区二区在线电影| 无码日韩精品一区二区三区免费| 亚洲日韩国产欧美一区二区三区| 亚洲国产一区二区a毛片| 国产成人精品一区二区三区免费 | 一区二区三区四区视频在线| 免费高清av一区二区三区| 日韩一区二区超清视频| 日本一区频道在线视频| 丝袜美腿一区二区三区| 久久国产免费一区二区三区| 久久一区二区三区精品| 久久99热狠狠色精品一区 | 曰韩精品无码一区二区三区| 日本一区二区高清不卡| 精品乱人伦一区二区| 日韩免费无码一区二区视频| 午夜视频一区二区| 中文字幕在线一区二区三区| 国产精品一区二区久久不卡 | 国内精自品线一区91| 一区二区三区免费在线视频| 中文字幕无码一区二区免费|