成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

C語言的那些小秘密之函數指針

開發 后端
我們經常會聽到這樣的說法,不懂得函數指針就不是真正的C語言高手。我們不管這句話對與否,但是它都從側面反應出了函數指針的重要性,所以我們還是有必要掌握對函數指針的使用。先來看看函數指針的定義吧。

函數是由執行語句組成的指令序列或者代碼,這些代碼的有序集合根據其大小被分配到一定的內存空間中,這一片內存空間的起始地址就成為函數的地址,不同的函數有不同的函數地址,編譯器通過函數名來索引函數的入口地址,為了方便操作類型屬性相同的函數,c/c++引入了函數指針,函數指針就是指向代碼入口地址的指針,是指向函數的指針變量。 因而“函數指針”本身首先應該是指針變量,只不過該指針變量指向函數。這正如用指針變量可指向整形變量、字符型、數組一樣,這里是指向函數。C在編譯時,每一個函數都有一個入口地址,該入口地址就是函數指針所指向的地址。有了指向函數的指針變量后,可用該指針變量調用函數,就如同用指針變量可引用其他類型變量一樣,在這些概念上是一致的。函數指針有兩個用途:調用函數和做函數的參數。

[[128816]]

函數指針的聲明方法為:

數據類型標志符 (指針變量名) (形參列表);

“函數類型”說明函數的返回類型,由于“”的優先級高于“*”,所以指針變量名外的括號必不可少,后面的“形參列表”表示指針變量指向的函數所帶的參數列表。例如:

  1. int function(int x,int y); /* 聲明一個函數 */ 
  2. int (*f) (int x,int y); /* 聲明一個函數指針 */ 

f=function; /* 將function函數的首地址賦給指針f */

賦值時函數function不帶括號,也不帶參數,由于function代表函數的首地址,因此經過賦值以后,指針f就指向函數function(int x,int y);的代碼的首地址。

下面的程序說明了函數指針調用函數的方法:

例一、

 

  1. #include 
  2.  
  3. int max ( int x, int y){ return x>y?x:y;} 
  4.  
  5. int min ( int x, int y){ return x 
  6.  
  7. void main 
  8.  
  9. int ( *f ) ( int x, int y)=max; 
  10.  
  11. //f=&max; 
  12.  
  13. printf ( "%d,%d\t", max (2,6), (f)(5,4)); 
  14.  
  15. f=min; 
  16.  
  17. printf (" %d,%d\t" , min (2,6), (f)(5,4)); 
  18.  

 

注意:以上代碼的紅色部分我們將會在接下來的代碼分析部分進行講解,讀者也可以思考下如果運行注釋部分,結果是否還是正確的呢?

f是指向函數的指針變量,所以可把函數max賦給f作為f的值,即把max的入口地址賦給f,以后就可以用f來調用該函數,實際上f和max都指向同一個入口地址,不同就是f是一個指針變量,不像函數名稱那樣是死的,它可以指向任何函數,就看你想怎么做了。在程序中把哪個函數的地址賦給它,它就指向哪個函數。而后用指針變量調用它,因此可以先后指向不同的函數。不過注意,指向函數的指針變量沒有++和--運算,用時要小心。

函數括號中的形參可有可無,視情況而定,不過,在某些編譯器中這是不能通過的。這個例子的補充如下。

1.定義函數指針類型:

  1. typedef int (*fun_ptr)(int,int); 

2.申明變量,賦值:

  1. fun_ptr max_func=max; 

也就是說,賦給函數指針的函數應該和函數指針所指的函數原型是一致的。

例二、

 

  1. #include 
  2.  
  3. void FileFunc 
  4.  
  5.  
  6. printf("FileFunc\n"); 
  7.  
  8.  
  9. void EditFunc 
  10.  
  11.  
  12. printf("EditFunc\n"); 
  13.  
  14.  
  15. void main 
  16.  
  17.  
  18. typedef void (*funcp); 
  19.  
  20. funcp pfun= FileFunc; 
  21.  
  22. pfun; 
  23.  
  24. pfun = EditFunc; 
  25.  
  26. pfun; 
  27.  

看了上面兩段代碼,應該都知道如何用函數指針來調用函數了,但是我們剛剛在上面的描述中留下過一個問題,就是運行注釋部分f=&max;結果是否還是正確的呢?下面我就給出上面兩個運行結果的對別,然后來分析下原因。

C語言的那些小秘密之函數指針

 

把注釋部分加進去的運行結果為:

C語言的那些小秘密之函數指針

 

對比以上的運行結果可以看出,f=&max語句被執行時的結果和沒有被執行時的結果是一樣的。為什么會出現這樣的結果呢?答案是這是編譯器處理的,max本身就是個地址,它沒有放到任何變量里,自然沒有取它的地址一說。所以我們可以看看在調試的過程中&max的值和max的值是一樣的。調試代碼如下:

 

  1. root@ubuntu:/home/shiyan# gdb ss 
  2.  
  3. GNU gdb (Ubuntu/Linaro 7.2-1ubuntu11) 7.2 
  4.  
  5. Copyright (C) 2010 Free Software Foundation, Inc. 
  6.  
  7. License GPLv3+: GNU GPL version 3 or later 
  8.  
  9. This is free software: you are free to change and redistribute it. 
  10.  
  11. There is NO WARRANTY, to the extent permitted by law. Type "show copying" 
  12.  
  13. and "show warranty" for details. 
  14.  
  15. This GDB was configured as "i686-linux-gnu"
  16.  
  17. For bug reporting instructions, please see: 
  18.  
  19. ... 
  20.  
  21. Reading symbols from /home/shiyan/ss...done. 
  22.  
  23. (gdb) list 
  24.  
  25. 1 #include 
  26.  
  27. 2 int max ( int x, int y){ return x>y?x:y;} 
  28.  
  29. 3 int min ( int x, int y){ return x 
  30.  
  31. 4 void main 
  32.  
  33. 5 { int ( *f ) ( int x, int y)=max; 
  34.  
  35. 6 //f=&max; 
  36.  
  37. 7 printf ( "%d,%d\t", max (2,6), (f)(5,4)); 
  38.  
  39. 8 f=min; 
  40.  
  41. 9 printf (" %d,%d\t" , min (2,6), (f)(5,4)); 
  42.  
  43. 10 } 
  44.  
  45. (gdb) b 4 
  46.  
  47. Breakpoint 1 at 0x80483ec: file hanshu.c, line 4
  48.  
  49. (gdb) r 
  50.  
  51. Starting program: /home/shiyan/ss 
  52.  
  53. Breakpoint 1, main at hanshu.c:5 
  54.  
  55. (gdb) print max 
  56.  
  57. $1 = {int (intint)} 0x80483c4 
  58.  
  59. (gdb) print f 
  60.  
  61. $2 = (int (*)(intint)) 0xbffff6c8 
  62.  
  63. (gdb) s 
  64.  
  65. (gdb) 
  66.  
  67. max (x=5, y=4) at hanshu.c:2 
  68.  
  69. 2 int max ( int x, int y){ return x>y?x:y;} 
  70.  
  71. (gdb) print max 
  72.  
  73. $3 = {int (intint)} 0x80483c4 
  74.  
  75. (gdb) print &max 
  76.  
  77. $4 = (int (*)(intint)) 0x80483c4 
  78.  
  79. (gdb) print *max 
  80.  
  81. $5 = {int (intint)} 0x80483c4 
  82.  
  83. (gdb) s 
  84.  
  85. max (x=2, y=6) at hanshu.c:2 
  86.  
  87. (gdb) s 
  88.  
  89. main at hanshu.c:8 
  90.  
  91. 8 f=min; 
  92.  
  93. (gdb) print min 
  94.  
  95. $6 = {int (intint)} 0x80483d3 
  96.  
  97. (gdb) print &min 
  98.  
  99. $7 = (int (*)(intint)) 0x80483d3 
  100.  
  101. (gdb) print *min 
  102.  
  103. $8 = {int (intint)} 0x80483d3 
  104.  
  105. (gdb) s 
  106.  
  107. 9 printf (" %d,%d\t" , min (2,6), (f)(5,4)); 
  108.  
  109. (gdb) print f 
  110.  
  111. $9 = (int (*)(intint)) 0x80483d3 
  112.  
  113. (gdb) print &f 
  114.  
  115. $10 = (int (**)(intint)) 0xbffff6ac 
  116.  
  117. (gdb) print *f 
  118.  
  119. $11 = {int (intint)} 0x80483d3 
  120.  
  121. (gdb) s 
  122.  
  123. min (x=5, y=4) at hanshu.c:3 
  124.  
  125. 3 int min ( int x, int y){ return x 
  126.  
  127. (gdb) s 
  128.  
  129. min (x=2, y=6) at hanshu.c:3 
  130.  
  131. (gdb) print min 
  132.  
  133. $12 = {int (intint)} 0x80483d3 
  134.  
  135. (gdb) s 
  136.  
  137. main at hanshu.c:10 
  138.  
  139. 10 } 

在調試的過程中我print了很多的信息,細心的讀者肯定能獲得更多的收獲,尤其是對變量f的print,讀者可以自己閱讀,學到更多的東西。我給出的只是一個參考的調試方式,希望讀者能夠舉一反三,自己對代碼進行實際的調試,加深理解。

上面說的都是用指針來實現函數的調用,接下來我們看一個用函數指針作為參數的用法。

  1. #include 
  2.  
  3. using namespace std; 
  4.  
  5. typedef int (*print)(int ); 
  6.  
  7. int fun1(int i) 
  8.  
  9.  
  10. return (int)i; 
  11.  
  12.  
  13. void fun2(int j,print prt) 
  14.  
  15.  
  16. for(int k=0;k 
  17.  
  18. cout<<'\t'
  19.  
  20.  
  21. void main 
  22.  
  23.  
  24. int i=10; 
  25.  
  26. fun2(i,fun1); 
  27.  

運行結果如下:

 

 

看了上面的描述,我想都對函數指針的概念有了大致的了解,另外一個希望大家不要混淆的概念就是指針函數,,這兩個概念都是簡稱,指針函數是指帶指針的函數,即本質是一個函數。我們知道函數都又有返回類型(如果不返回值,則為無值型,即為void),只不過指針函數返回類型是某一類型的指針。

其定義格式如下所示:

返回類型標識符 *返回名稱(形式參數表)

{ 函數體}

返回類型可以是任何基本類型和復合類型。返回指針的函數的用途十分廣泛。事實上,每一個函數,即使它不帶有返回某種類型的指針,它本身都有一個入口地址,該地址相當于一個指針。比如函數返回一個整型值,實際上也相當于返回一個指針變量的值,不過這時的變量是函數本身而已,而整個函數相當于一個“變量”,關于函數的返回值問題我將在下一章來講解,本章到此為止。希望以上內容對你有所幫助!

C語言博大精深,由于本人水平有限,博客中的不妥或錯誤之處在所難免,殷切希望讀者批評指正。同時也歡迎讀者共同探討相關的內容,如果樂意交流的話請留下你寶貴的意見。

責任編輯:王雪燕 來源: 電子產品世界
相關推薦

2015-04-14 09:46:09

Apple Watch秘密

2019-07-22 09:46:28

WebSocketNginx服務器

2019-08-30 08:39:33

WebSocketNginx服務器

2025-03-19 08:40:00

2019-09-10 16:25:19

Python內存空對象

2015-11-27 10:13:19

數據中心

2019-06-05 12:49:07

云辦公

2016-01-08 14:23:55

2012-03-23 10:27:08

觸屏手機點擊區域

2017-12-15 21:46:45

2010-05-13 00:03:44

2013-11-25 10:43:32

谷歌微軟

2018-08-15 08:47:20

2011-12-09 17:41:56

2010-10-12 12:10:52

增強無線網絡信號

2016-03-31 14:51:33

多云計算多云部署多云管理

2023-12-12 08:50:22

MySQL隱式轉換varchar

2015-03-06 10:33:02

2021-06-10 05:17:52

QQ應用手機QQ

2015-11-09 11:24:48

數據中心數據中心優化
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 中文字幕久久久 | 久久久www成人免费无遮挡大片 | 粉嫩国产精品一区二区在线观看 | 黄视频网站在线 | 在线视频一区二区三区 | av手机免费在线观看 | 91精品国产乱码久久蜜臀 | 国内精品视频一区二区三区 | 午夜精品视频 | 亚洲精品乱码久久久久久9色 | 久草欧美视频 | 在线观看视频福利 | 精品中文字幕一区二区三区 | 亚洲+变态+欧美+另类+精品 | 免费精品一区 | 亚洲午夜精品 | 在线观看亚洲精品 | 国产成人啪免费观看软件 | 国产在线精品区 | 成人国产午夜在线观看 | 国产综合在线视频 | 亚洲人精品午夜 | 国户精品久久久久久久久久久不卡 | 欧美综合久久 | av一二三四 | 久久久久久亚洲精品 | 成人在线视频免费播放 | 在线成人免费视频 | 黑人巨大精品欧美一区二区免费 | 99精品欧美一区二区蜜桃免费 | 欧美一区二区 | 亚洲欧洲在线视频 | 操操日 | 一区二区三区回区在观看免费视频 | 中文字幕精品视频 | 久久久精品| 欧美综合久久 | 狠狠插狠狠操 | 久热国产在线 | 久久国产区| 中文字幕精品视频 |