国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 編程 > C > 正文

C語(yǔ)言中的函數(shù)指針學(xué)習(xí)筆記

2020-01-26 14:38:15
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

一、定義函數(shù)指針

return_type (*func_pointer)(parameter_list)

普通指針變量的定義

int * p;char * pointer;

類(lèi)型的限定都在變量前面;
函數(shù)指針類(lèi)型的限定是前后都有,前面是返回類(lèi)型,后面是輸入?yún)?shù)。

2016420154232853.png (449×127)

利用typedef 可以簡(jiǎn)化上面的表達(dá)方式。

typedef return_type (*FunctionPointer) (parameter_list);FunctionPointer func_pointer;

這樣是不是容易讀了,和上面的功能一樣,定義了一個(gè)返回類(lèi)型為return_type ,輸入?yún)?shù)為parameter_list的函數(shù)指針。

二、定義返回函數(shù)指針的函數(shù)
return_type(*function(func_parameter_list))(parameter_list)

2016420154256143.png (558×129)

方框圈出來(lái)的表示返回類(lèi)型為函數(shù)指針,剩下的部分就表示一個(gè)function函數(shù),輸入?yún)?shù)為func_parameter_list。
它就等價(jià)于 FunctionPointer function(func_parameter_list); 。
再看看:

void ( *signal( int sig, void (* handler)( int )))( int );

2016420154323228.png (400×63)

signal是一個(gè)返回函數(shù)指針的函數(shù),signal的輸入為int 變量和一個(gè)函數(shù)指針。

三、函數(shù)指針的使用

#include <stdio.h> int add(int a, int b); void main() {   int(*fun1)(int a, int b) = add;   int(*fun2)(int a, int b) = &add;   int(*fun3)(int a, int b) = *add;   printf("%d/n", fun1(1, 2));   printf("%d/n", fun2(1, 2));   printf("%d/n", fun3(1, 2));   char input[10];   gets(input); } int add(int a, int b) {   return a + b; }

函數(shù)名會(huì)被隱式的轉(zhuǎn)變?yōu)橹羔槪懊婕?和&操作符都不起作用,printf的結(jié)果都是3。

四、神奇的代碼

int (*(*pf())())(){ return nullptr; }

哇哦,這是個(gè)什么函數(shù)!畫(huà)個(gè)框框分解它

2016420154405912.png (400×63)

小框表示返回的是一個(gè)函數(shù)指針,在圈個(gè)大框,又是一個(gè)函數(shù)指針。
它就表示,pf() 返回的是一個(gè)函數(shù)指針,這個(gè)函數(shù)指針對(duì)應(yīng)一個(gè)無(wú)輸入?yún)?shù)的函數(shù):返回值也是函數(shù)指針(對(duì)應(yīng)無(wú)輸入?yún)?shù)的函數(shù),返回值為int類(lèi)型)。好復(fù)雜啊,有點(diǎn)暈!
利用typedef 簡(jiǎn)化一下。

typedef int(*Fun1) (); typedef Fun1(*Fun2) (); Fun2 pf() {    return nullptr; }

這樣看就舒服多了。

五、這又是什么鬼!

(*(void(*) ())0)();

畫(huà)個(gè)框看看:

2016420154437319.png (299×61)

小框里代表一個(gè)函數(shù)指針,常數(shù)前面加括號(hào)代表類(lèi)型的強(qiáng)制轉(zhuǎn)換。咦,它把0強(qiáng)制轉(zhuǎn)換成了一個(gè)函數(shù)指針,并執(zhí)行!這是什么操作啊!
六、一段驗(yàn)證代碼

#include <stdio.h> typedef int Function(int, int); typedef int(*FunctionPointer1) (int, int); typedef FunctionPointer1(*FunctionPointer2) (); int fun1(int a, int b) {   return a + b; } FunctionPointer1 fun2() {   return fun1; } FunctionPointer2 fun3() {   return fun2; } int(*(*fun4())())(int, int) {   return fun2; } void main() {   Function* fuction = fun1;   FunctionPointer1 fun = fun1;   int a = fun3()()(3, 4);   int b = fun4()()(5, 6);   printf("%d/n%d/n", a, b);   printf("fun1:%d/n*fun1:%d/n&fun1:%d", fun1, *fun1, &fun1);   printf("fun:%d/n*fun:%d/n&fun:%d", fun, *fun, &fun);   char chars[10];   gets(chars); }

函數(shù)名前面加不加*,&操作符,都是一個(gè)效果;函數(shù)指針前面加不加*操作符是一個(gè)效果,但是加上&操作符就代表著取指針的地址了。
可以通過(guò)typedef int Function(int, int); 為一種類(lèi)型的函數(shù)定義別名,但是使用的時(shí)候只能定義指針形式的變量:

Function* fuction = fun1;

七、一個(gè)問(wèn)題
在stackoverflow上偶爾看到如下的問(wèn)題,代碼如下

#includevoid hello() { printf("hello"); }int hello_1(){    printf("hello 1");    return 0;} int main(void) {  (*****hello)();  (****hello_1)();}

   執(zhí)行結(jié)果是無(wú)論hello前面有多少個(gè)指針?lè)?hào),都是執(zhí)行hello()函數(shù),打印“hello”。
  為什么出現(xiàn)這樣的結(jié)果呢:
    用指針指向一個(gè)函數(shù)是OK的,但是仍然還要被轉(zhuǎn)化為一個(gè)function pointer。其實(shí)使用*來(lái)指向一個(gè)函數(shù) == CALL這個(gè)函數(shù)。因此無(wú)論指向多少次,仍然也是調(diào)用這個(gè)函數(shù)。
為什么一個(gè)函數(shù)會(huì)被轉(zhuǎn)化成一個(gè)指針呢?答案就是將函數(shù)默認(rèn)的轉(zhuǎn)換成函數(shù)指針,可以減少&的使用,編譯器默認(rèn)的將函數(shù)轉(zhuǎn)化為函數(shù)指針,也省得你每次調(diào)用函數(shù)時(shí)加*調(diào)用函數(shù)。
  哈哈,也就是我們之前說(shuō)的,函數(shù)即指針。似乎有點(diǎn)不是很清晰,再看下面的例子

void foo() {    printf("Foo to you too!.../n");}; int a = 2;int* test(){    return &a;}int main(){  int i;  void (*p1_foo)() = foo;  void (*p2_foo)() = *foo;  void (*p3_foo)() = &foo;  void (*p4_foo)() = *&foo;  void (*p5_foo)() = &*foo;  void (*p6_foo)() = **foo;  void (*p7_foo)() = **********************foo;   (*p1_foo)();  (*p2_foo)();  (*p3_foo)();  (*p4_foo)();  (*p5_foo)();  (*p6_foo)();  (*p7_foo)();  i = *(***test)();printf("i=%d/n",i);}

上面的列子不出例外,都能正常打印我們想要的數(shù)據(jù)。
但是對(duì)于&,則要進(jìn)行仔細(xì)的分析一下:
&對(duì)于一個(gè)函數(shù)的操作,是返回一個(gè)指針,指向函數(shù)的指針,如果在對(duì)此指針執(zhí)行&也就是&&foo,則會(huì)返回error,因?yàn)?foo是一個(gè)指針數(shù)值,也就是一個(gè)rvalue類(lèi)型,再對(duì)他進(jìn)行&操作,顯然是返回error的。

&&foo  //EROOR&*&*&*&*&*&*foo //OK&******&foo  //OK

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表

圖片精選

主站蜘蛛池模板: 商都县| 故城县| 睢宁县| 河源市| 罗田县| 正蓝旗| 安平县| 建水县| 嘉峪关市| 甘泉县| 鱼台县| 封开县| 德安县| 内乡县| 大理市| 塘沽区| 许昌市| 弋阳县| 双牌县| 荔浦县| 上蔡县| 南阳市| 河北区| 万山特区| 北票市| 天等县| 闻喜县| 沙坪坝区| 正镶白旗| 湟中县| 建平县| 鄄城县| 正安县| 陇南市| 石嘴山市| 图木舒克市| 中西区| 米林县| 黄陵县| 白山市| 明溪县|