日韩久久久精品,亚洲精品久久久久久久久久久,亚洲欧美一区二区三区国产精品 ,一区二区福利

深入理解C指針之三:指針和函數(shù)

系統(tǒng) 2523 0
原文: 深入理解C指針之三:指針和函數(shù)

  理解函數(shù)和指針的結(jié)合使用,需要理解程序棧。大部分現(xiàn)代的塊結(jié)構(gòu)語言,比如C,都用到了程序棧來支持函數(shù)的運(yùn)行。調(diào)用函數(shù)時,會創(chuàng)建函數(shù)的棧幀并將其推到程序棧上。函數(shù)返回時,其棧幀從程序棧上彈出。

  在使用函數(shù)時,有兩種情況指針很有用。一種是將指針作為參數(shù)傳遞給函數(shù),函數(shù)可以修改指針?biāo)玫臄?shù)據(jù),可以高效的傳遞大塊數(shù)據(jù)。另一種是聲明函數(shù)指針。

  程序的棧和堆

  程序的棧和堆是C程序的重要運(yùn)行時元素。程序棧是支持函數(shù)執(zhí)行的內(nèi)存區(qū)域,通常和堆共享一塊內(nèi)存區(qū)域。通常程序棧在區(qū)域的下部,堆在上部。程序棧存放棧幀(stack frame),棧幀有時候也稱為活躍記錄或活躍幀。棧幀存放函數(shù)參數(shù)和局部變量。堆則管理動態(tài)內(nèi)存。

  調(diào)用函數(shù)時,函數(shù)的棧幀被推到棧上,棧向上“長出”一個棧幀。當(dāng)函數(shù)終止時,其棧幀從程序上彈出。棧幀所使用的內(nèi)存不會被清理,但有可能被另一個棧幀覆蓋。

  棧幀由以下幾種元素組成:

  * 返回地址。函數(shù)完成后要返回的程序內(nèi)部地址。

  * 局部數(shù)據(jù)存儲。為局部變量分配的內(nèi)存。

  * 參數(shù)存儲。為函數(shù)參數(shù)分配的內(nèi)存。

  * 棧指針和基指針。運(yùn)行時系統(tǒng)用來管理棧的指針。

  棧指針通常指向棧頂部。基指針(幀指針)通常存在并指向棧幀內(nèi)部的地址,比如返回地址,用來協(xié)助訪問棧幀內(nèi)部的元素。這兩個指針都是運(yùn)行時系統(tǒng)用來管理程序棧的地址。系統(tǒng)在創(chuàng)建棧幀時,將參數(shù)以跟聲明時相反的順序推到幀上,最后推入局部變量。C把塊語句當(dāng)做“微型”函數(shù),會在適當(dāng)?shù)臅r候?qū)⑵渫迫霔:蛷臈I蠌棾觥?

  參數(shù)和局部變量的精確地址可能會變化,不過順序一般不變。這一點可以解釋參數(shù)和變量分配內(nèi)存的相對順序。將棧幀推到程序棧上時,系統(tǒng)可能會好近內(nèi)存,這種情況稱為棧溢出。要記住每個線程通常都有自己的程序棧,一個或多個線程訪問內(nèi)存中的同一個對象可能會導(dǎo)致沖突。

  通過指針傳遞和返回數(shù)據(jù)

  傳遞參數(shù)(包括指針)的時候,傳遞的是它們的值的副本。當(dāng)涉及大型數(shù)據(jù)結(jié)構(gòu)時,傳遞參數(shù)的指針會更高效。傳遞對象的指針意味著不需要復(fù)制對象,但可以通過指針訪問對象。

  用指針來傳遞數(shù)據(jù)的一個主要原因是函數(shù)可以修改數(shù)據(jù)。如果不希望函數(shù)修改數(shù)據(jù),可以傳遞指向常量的指針。

  從函數(shù)返回指針有兩種情況:一種是在函數(shù)內(nèi)部為指針分配內(nèi)存并返回指向內(nèi)存的指針,另一種是函數(shù)的調(diào)用者負(fù)責(zé)指針內(nèi)存的分配和釋放。從函數(shù)返回指針可能存在幾個潛在的問題:

  * 返回未初始化的指針。

  * 返回指向無效地址的指針。

  * 返回局部變量的指針。

  * 返回指針但是沒有釋放內(nèi)存。

  設(shè)想一下在函數(shù)中聲明一個指針并為該指針分配內(nèi)存,但是在調(diào)用該函數(shù)的時候沒有使用一個指針變量來接受函數(shù)的返回值,因此我們丟失了該分配內(nèi)存的地址,導(dǎo)致內(nèi)存泄露。

  局部數(shù)據(jù)指針是指當(dāng)函數(shù)返回的時候,(非動態(tài)分配的)局部數(shù)據(jù)的地址也就無效了。動態(tài)分配的內(nèi)存與此不同,存在于堆上,即使函數(shù)返回也不受影響。當(dāng)變量為static,就會在棧幀外部為其分配內(nèi)存,每次調(diào)用函數(shù)都會訪問同一塊內(nèi)存。

  在將指針作為參數(shù)傳遞時,在使用之前判斷指針是否為NULL是個好習(xí)慣。 重復(fù)free一個指針會引發(fā)錯誤,在free之前也應(yīng)判斷指針是否為NULL。而且在釋放之后將指針置為NULL。

  傳遞指針將允許我們修改指針指向的數(shù)據(jù),如果我們想修改的是指針怎么辦?當(dāng)然是傳遞指向指針的指針了。

  函數(shù)指針

  函數(shù)指針是持有函數(shù)地址的指針。通過將函數(shù)指針作為參數(shù)傳遞,使我們避免將事件處理程序硬編碼進(jìn)函數(shù)里,更加靈活。

      void (*foo)();


    

?   void是返回類型,foo是指針變量名,后邊的括號里是參數(shù)。

      int(*fptr1)(int);

int square(int num)

{

        return num*num;

}

fptr1 = square;

int n = 5;

printf(" result is %d\n", fptr1(n));


    

?  使用函數(shù)的名字直接給函數(shù)指針賦值,它會把函數(shù)的地址賦給指針。也可以對函數(shù)名字使用取地址操作符,但是意思是一樣的,在此處上下文中會忽略取地址操作符。可以為函數(shù)指針聲明一個類型定義,通過類型定義來聲明函數(shù)指針。

      typedef int (*funcptr)(int);

funcptr ptr2;

ptr2 = square;


    

?  傳遞函數(shù)指針只需把函數(shù)指針聲明為參數(shù)即可。

      funcptr ptr2;

ptr2 = square;

int compute(funcptr squ, int num)

{

        return squ(num);

}

compute(ptr2,n);


    

?  返回函數(shù)指針需要把函數(shù)的返回類型聲明為函數(shù)指針。函數(shù)指針數(shù)組可以基于某些條件選擇要執(zhí)行的函數(shù),聲明這種數(shù)組只要把函數(shù)指針聲明為數(shù)組的類型即可。

      typedef int (*operation)(int,int);

operation operations[128] = {NULL};//使用NULL來初始化所有數(shù)組元素


    

  我們可以用相等和不等操作符來比較函數(shù)指針。不同的函數(shù)指針的長度不一定相等。雖然可以將一種函數(shù)指針轉(zhuǎn)換為另一種函數(shù)指針,但是應(yīng)該謹(jǐn)慎使用這種方法,因為運(yùn)行時系統(tǒng)不會驗證函數(shù)指針?biāo)玫膮?shù)是否正確。不應(yīng)該把函數(shù)指針轉(zhuǎn)換成void*指針。基本指針用作占位符,用來交換函數(shù)指針的值。一定要確保給函數(shù)指針傳遞的參數(shù)是正確的,否則會造成不確定行為。

  總體來說,函數(shù)指針允許應(yīng)用程序根據(jù)不同的條件執(zhí)行不同的函數(shù),對 控制應(yīng)用 序內(nèi)的執(zhí) 行序列很有用。

深入理解C指針之三:指針和函數(shù)


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯(lián)系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發(fā)表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 承德县| 高安市| 怀宁县| 安达市| 绥德县| 鄯善县| 淮滨县| 含山县| 会昌县| 东海县| 东阳市| 太仆寺旗| 金秀| 西充县| 乌兰浩特市| 屏东县| 嫩江县| 平南县| 古交市| 边坝县| 通榆县| 日喀则市| 龙岩市| 民勤县| 台安县| 象山县| 安陆市| 麟游县| 蒙山县| 新营市| 通江县| 罗甸县| 松桃| 三亚市| 江油市| 嘉鱼县| 婺源县| 崇文区| 棋牌| 仁怀市| 驻马店市|