亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

深入理解C指針之三:指針和函數

系統 2138 0
原文: 深入理解C指針之三:指針和函數

  理解函數和指針的結合使用,需要理解程序棧。大部分現代的塊結構語言,比如C,都用到了程序棧來支持函數的運行。調用函數時,會創建函數的棧幀并將其推到程序棧上。函數返回時,其棧幀從程序棧上彈出。

  在使用函數時,有兩種情況指針很有用。一種是將指針作為參數傳遞給函數,函數可以修改指針所引用的數據,可以高效的傳遞大塊數據。另一種是聲明函數指針。

  程序的棧和堆

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

  調用函數時,函數的棧幀被推到棧上,棧向上“長出”一個棧幀。當函數終止時,其棧幀從程序上彈出。棧幀所使用的內存不會被清理,但有可能被另一個棧幀覆蓋。

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

  * 返回地址。函數完成后要返回的程序內部地址。

  * 局部數據存儲。為局部變量分配的內存。

  * 參數存儲。為函數參數分配的內存。

  * 棧指針和基指針。運行時系統用來管理棧的指針。

  棧指針通常指向棧頂部。基指針(幀指針)通常存在并指向棧幀內部的地址,比如返回地址,用來協助訪問棧幀內部的元素。這兩個指針都是運行時系統用來管理程序棧的地址。系統在創建棧幀時,將參數以跟聲明時相反的順序推到幀上,最后推入局部變量。C把塊語句當做“微型”函數,會在適當的時候將其推入棧和從棧上彈出。

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

  通過指針傳遞和返回數據

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

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

  從函數返回指針有兩種情況:一種是在函數內部為指針分配內存并返回指向內存的指針,另一種是函數的調用者負責指針內存的分配和釋放。從函數返回指針可能存在幾個潛在的問題:

  * 返回未初始化的指針。

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

  * 返回局部變量的指針。

  * 返回指針但是沒有釋放內存。

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

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

  在將指針作為參數傳遞時,在使用之前判斷指針是否為NULL是個好習慣。 重復free一個指針會引發錯誤,在free之前也應判斷指針是否為NULL。而且在釋放之后將指針置為NULL。

  傳遞指針將允許我們修改指針指向的數據,如果我們想修改的是指針怎么辦?當然是傳遞指向指針的指針了。

  函數指針

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

      void (*foo)();


    

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

      int(*fptr1)(int);

int square(int num)

{

        return num*num;

}

fptr1 = square;

int n = 5;

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


    

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

      typedef int (*funcptr)(int);

funcptr ptr2;

ptr2 = square;


    

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

      funcptr ptr2;

ptr2 = square;

int compute(funcptr squ, int num)

{

        return squ(num);

}

compute(ptr2,n);


    

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

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

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


    

  我們可以用相等和不等操作符來比較函數指針。不同的函數指針的長度不一定相等。雖然可以將一種函數指針轉換為另一種函數指針,但是應該謹慎使用這種方法,因為運行時系統不會驗證函數指針所用的參數是否正確。不應該把函數指針轉換成void*指針。基本指針用作占位符,用來交換函數指針的值。一定要確保給函數指針傳遞的參數是正確的,否則會造成不確定行為。

  總體來說,函數指針允許應用程序根據不同的條件執行不同的函數,對 控制應用 序內的執 行序列很有用。

深入理解C指針之三:指針和函數


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

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

【本文對您有幫助就好】

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

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 二级毛片免费观看全程 | 国产大片在线观看 | 中文字幕在线一区二区三区 | 欧美成人怡红院在线观看 | 九七97影院理论片手机在线观看 | 国产精品一区在线免费观看 | 狠狠色噜噜狠狠狠狠米奇777 | 婷婷在线视频观看 | 久久伊人成人 | 成人美女免费网站视频 | 香蕉尹人 | 国产福利影院在线观看 | 国内自拍青青草 | 午夜18免费观看 | 九九草在线观看 | 亚洲欧美中文字幕高清在线一 | 亚洲另类伦春色综合妖色成人网 | 成年黄页免费大全网站 | 国产香蕉一区二区精品视频 | 美女撒尿毛片免费看 | 中文精品久久久久国产网站 | 性欧美xo视频在线观看 | 97国产精品视频观看一 | 国产成人精品久久一区二区小说 | 国产精品国产三级国产an | 免费两性的视频网站 | 欧产日产国产精品专区 | 亚洲成人小视频 | 国产日韩在线 | 豆奶视频污 | 亚洲综合区小说区激情区噜噜 | 久草视频在线资源 | 欧美成年黄网站色高清视频 | 日韩中文字幕精品视频在线 | 综合网久久| 久久国产高清字幕中文 | 欧美成人免费视频a | 免费视频不卡 | 四虎影院免费视频 | 精品国产一区二区三区久 | 亚洲精品一区二区三区网址 |