最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解C語言未初始化的局部變量是多少

 更新時間:2020年07月19日 10:44:27   作者:dog250  
這篇文章主要給大家介紹了關(guān)于C語言未初始化的局部變量是多少,文中通過示例代碼以及圖文介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧

C語言中,未初始化的局部變量到底是多少?

答案往往是:

  • 與編譯器有關(guān)。
  • 可能但不保證初始化為0。
  • 未確定。

總之,全部都是些一本正經(jīng)的形而上答案,這很令人討厭。

但凡一些人給你滔滔不絕地扯編譯器,C庫,處理器體系結(jié)構(gòu)卻給不出一個實(shí)際場景復(fù)現(xiàn)問題的時候,這人大概率在扯淡。

又是周五回家時,大巴車上作短文一篇。

其實(shí),這個問題本身就是錯誤的問法,說全了能講10萬字,我們只要能在特定場景下確定其特定行為就OK了,當(dāng)然,這就需要設(shè)計(jì)一個比較OK的實(shí)驗(yàn)。

在演示一個實(shí)際代碼行為之前,先給出一個知識, CPU不認(rèn)識變量,更無法識別變量的名字,CPU只會從特定的內(nèi)存位置取值或者將值存到特定的內(nèi)存位置,因此當(dāng)問一個變量的值是多少的時候,必須要知道這個變量對應(yīng)的值被保存在什么地方。

來看下面的代碼:

#include <stdio.h>

void func1()
{
 int a;
 printf("func1:%d\n", a);
 a = 12345;
}

void func2()
{
 int b;
 printf("func2:%d\n", b);
}

void func4()
{
 int d;
 printf("func3:%d\n", d);
}

void func3()
{
 int c;
 printf("func3:%d\n", c);
 c = 54321;
 func4();
}

void test_call()
{
 func3();
}

int main(int argc, char **argv)
{
 func1();
 func2();

 test_call();
}

我們有func1~func4一共4個函數(shù),其內(nèi)部均有一個未初始化的局部變量,它們的值到底是多少呢?

對于這種局部變量,它們的值取決于:

  • 變量在棧中的位置。
  • 變量對應(yīng)的棧位置在 之前 有沒有被store過。

可以看到,上述第一點(diǎn)標(biāo)記了一個內(nèi)存位置,第二點(diǎn)則是代碼的行為,也就是說,只要有代碼去store對應(yīng)的位置, 且后續(xù)的代碼沒有reset該位置的值的話,該位置就會保留著原先被store后的值。

驗(yàn)證非常簡單,試一下就知道了:

[root@localhost test]# ./a.out
func1:0
func2:12345
func3:0
func3:0

按照函數(shù)調(diào)用棧幀的變化,func1的局部變量a和func2的局部變量b顯然是位于同一個位置的,在func1被調(diào)用時,這是一塊新的內(nèi)存(可能在進(jìn)入main之前有棧幀到達(dá)過這個位置),a的值取決于調(diào)入內(nèi)存該位置的頁面對應(yīng)偏移的初始值,這取決于操作系統(tǒng):

操作系統(tǒng)在分配給程序頁面時可能會將頁面clear為零頁。

棧的分配不會涉及C庫,這里顯然并不涉及C庫的行為,但類似malloc分配的內(nèi)存則涉及C庫了。

打印結(jié)果,a的值為0,我們認(rèn)為操作系統(tǒng)返回給了應(yīng)用程序零頁。接下來在func1中將其賦值12345之后函數(shù)返回,接下來調(diào)用func2的時候,在之前func1已經(jīng)退出的棧幀位置重建棧幀,對應(yīng)位置依然還是12345。

我沒有看到func1的ret操作后面有stack清0的代碼指令。效率考慮,也不該有這樣的指令。

再看test_call函數(shù),很明顯,func3和func4調(diào)用使用的并不是同一個棧幀,因此即便是在func3中對c賦值了54321,也不會影響在其棧幀之上的func4的棧幀對應(yīng)位置的值d。因此c和d的初始值均保持為0。

那么,初始化一個局部變量和不初始化一個局部變量,在指令層面上,區(qū)別在哪里呢?

很簡單,親眼看一下就知道,先看未初始化局部變量的func1:

// int a;
00000000004005ad <func1>:
 4005ad: 55      push %rbp
 4005ae: 48 89 e5    mov %rsp,%rbp
 4005b1: 48 83 ec 10    sub $0x10,%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 <printf@plt>
 4005c9: c7 45 fc 39 30 00 00 movl $0x3039,-0x4(%rbp)
 4005d0: c9      leaveq
 4005d1: c3      retq

再看初始化局部變量a為2222的版本:

// int a = 2222;
00000000004005ad <func1>:
 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 $0x0,%eax
 4005cb: e8 b0 fe ff ff   callq 400480 <printf@plt>
 4005d0: c7 45 fc 39 30 00 00 movl $0x3039,-0x4(%rbp)
 4005d7: c9      leaveq
 4005d8: c3      retq

僅僅差了一條指令:

 4005b5: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%rbp)

初始化的操作是依靠實(shí)實(shí)在在的指令完成的。

總結(jié)一句, 函數(shù)返回在pop出當(dāng)前棧幀的時候,并不會清理它遺留在棧幀里的數(shù)據(jù),下個函數(shù)調(diào)用再次重用到該棧幀的內(nèi)存時,未初始化的局部變量將會被遺留數(shù)據(jù)影響,從而變得不確定!

所以,記得初始化你的局部變量。如果你不這樣做,上帝終究會將你經(jīng)理了的。

總結(jié)

到此這篇關(guān)于詳解C語言未初始化的局部變量是多少的文章就介紹到這了,更多相關(guān)C語言未初始化的局部變量內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C++控制臺用定時器實(shí)例代碼

    C++控制臺用定時器實(shí)例代碼

    這篇文章主要介紹了C++控制臺用定時器實(shí)例代碼,分享了相關(guān)代碼示例,小編覺得還是挺不錯的,具有一定借鑒價值,需要的朋友可以參考下
    2018-02-02
  • QT實(shí)現(xiàn)QMessageBox中文按鈕示例詳解

    QT實(shí)現(xiàn)QMessageBox中文按鈕示例詳解

    這篇文章主要為大家詳細(xì)介紹了QT實(shí)現(xiàn)QMessageBox中文按鈕的相關(guān)知識,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-11-11
  • C語言驅(qū)動開發(fā)之內(nèi)核通過PEB獲取進(jìn)程參數(shù)

    C語言驅(qū)動開發(fā)之內(nèi)核通過PEB獲取進(jìn)程參數(shù)

    PEB結(jié)構(gòu)(Process Envirorment Block Structure)其中文名是進(jìn)程環(huán)境塊信息。本文將通過PEB實(shí)現(xiàn)獲取進(jìn)程參數(shù),感興趣的小伙伴可以了解一下
    2022-10-10
  • C++ 中的new 和 delete 運(yùn)算符及new和malloc的區(qū)別解析

    C++ 中的new 和 delete 運(yùn)算符及new和malloc的區(qū)別解析

    在C++中,又引出了一個新玩法:new 和 delete,在C++中,new是用來動態(tài)開辟內(nèi)存的,delete是用來釋放我們所動態(tài)開辟的內(nèi)存C++中的new和delete運(yùn)算符及new和malloc的區(qū)別解析,感興趣的朋友跟隨小編一起看看吧
    2024-11-11
  • C語言數(shù)字圖像處理之直方圖均衡化

    C語言數(shù)字圖像處理之直方圖均衡化

    這篇文章主要為大家詳細(xì)介紹了C語言數(shù)字圖像處理之直方圖均衡化,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-10-10
  • C語言詳解如何實(shí)現(xiàn)順序棧

    C語言詳解如何實(shí)現(xiàn)順序棧

    順序棧,就是用一組地址連續(xù)的存儲單元來存放棧元素,然后用一個棧結(jié)構(gòu)去維護(hù)一個棧。在C中,可用動態(tài)開辟的數(shù)組去表示,維護(hù)的棧結(jié)構(gòu)需要有一個棧底和一個棧頂指針
    2022-04-04
  • Swift編程中的泛型解析

    Swift編程中的泛型解析

    這篇文章主要介紹了Swift編程中的泛型解析,是Swift入門學(xué)習(xí)中的基礎(chǔ)知識,需要的朋友可以參考下
    2015-11-11
  • 深入理解c語言數(shù)組

    深入理解c語言數(shù)組

    這篇文章主要介紹了c語言數(shù)組,有需要的朋友可以參考一下
    2013-12-12
  • Qt實(shí)現(xiàn)TCP網(wǎng)絡(luò)編程

    Qt實(shí)現(xiàn)TCP網(wǎng)絡(luò)編程

    這篇文章主要為大家詳細(xì)介紹了Qt實(shí)現(xiàn)TCP網(wǎng)絡(luò)編程,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-08-08
  • C++堆和棧的區(qū)別與聯(lián)系講解

    C++堆和棧的區(qū)別與聯(lián)系講解

    今天小編就為大家分享一篇關(guān)于C++堆和棧的區(qū)別與聯(lián)系講解,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-04-04

最新評論

洱源县| 祁门县| 桑植县| 开原市| 西乌珠穆沁旗| 元谋县| 嫩江县| 南安市| 赤壁市| 金川县| 莒南县| 青州市| 凤翔县| 同心县| 正安县| 南川市| 镇平县| 托克托县| 淳安县| 澜沧| 图木舒克市| 广元市| 博罗县| 灯塔市| 新兴县| 昌图县| 凭祥市| 榆树市| 高阳县| 孙吴县| 新泰市| 于田县| 怀仁县| 隆回县| 迁西县| 北票市| 新泰市| 湘乡市| 桑日县| 左云县| 平原县|