C語言中的函數(shù)指針學(xué)習(xí)筆記
一、定義函數(shù)指針
return_type (*func_pointer)(parameter_list)
普通指針變量的定義
int * p; char * pointer;
類型的限定都在變量前面;
函數(shù)指針類型的限定是前后都有,前面是返回類型,后面是輸入?yún)?shù)。
利用typedef 可以簡化上面的表達(dá)方式。
typedef return_type (*FunctionPointer) (parameter_list); FunctionPointer func_pointer;
這樣是不是容易讀了,和上面的功能一樣,定義了一個(gè)返回類型為return_type ,輸入?yún)?shù)為parameter_list的函數(shù)指針。
二、定義返回函數(shù)指針的函數(shù)
return_type(*function(func_parameter_list))(parameter_list)
方框圈出來的表示返回類型為函數(shù)指針,剩下的部分就表示一個(gè)function函數(shù),輸入?yún)?shù)為func_parameter_list。
它就等價(jià)于 FunctionPointer function(func_parameter_list); 。
再看看:
void ( *signal( int sig, void (* handler)( int )))( int );
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ù)!畫個(gè)框框分解它
小框表示返回的是一個(gè)函數(shù)指針,在圈個(gè)大框,又是一個(gè)函數(shù)指針。
它就表示,pf() 返回的是一個(gè)函數(shù)指針,這個(gè)函數(shù)指針對(duì)應(yīng)一個(gè)無輸入?yún)?shù)的函數(shù):返回值也是函數(shù)指針(對(duì)應(yīng)無輸入?yún)?shù)的函數(shù),返回值為int類型)。好復(fù)雜啊,有點(diǎn)暈!
利用typedef 簡化一下。
typedef int(*Fun1) (); typedef Fun1(*Fun2) (); Fun2 pf() { return nullptr; }
這樣看就舒服多了。
五、這又是什么鬼!
(*(void(*) ())0)();
畫個(gè)框看看:
小框里代表一個(gè)函數(shù)指針,常數(shù)前面加括號(hào)代表類型的強(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è)效果,但是加上&操作符就代表著取指針的地址了。
可以通過typedef int Function(int, int); 為一種類型的函數(shù)定義別名,但是使用的時(shí)候只能定義指針形式的變量:
Function* fuction = fun1;
七、一個(gè)問題
在stackoverflow上偶爾看到如下的問題,代碼如下
#include void hello() { printf("hello"); } int hello_1() { printf("hello 1"); return 0; } int main(void) { (*****hello)(); (****hello_1)(); }
執(zhí)行結(jié)果是無論hello前面有多少個(gè)指針符號(hào),都是執(zhí)行hello()函數(shù),打印“hello”。
為什么出現(xiàn)這樣的結(jié)果呢:
用指針指向一個(gè)函數(shù)是OK的,但是仍然還要被轉(zhuǎn)化為一個(gè)function pointer。其實(shí)使用*來指向一個(gè)函數(shù) == CALL這個(gè)函數(shù)。因此無論指向多少次,仍然也是調(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ù)。
哈哈,也就是我們之前說的,函數(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類型,再對(duì)他進(jìn)行&操作,顯然是返回error的。
&&foo //EROOR &*&*&*&*&*&*foo //OK &******&foo //OK
上一篇:Android App仿微信界面切換時(shí)Tab圖標(biāo)變色效果的制作方法
欄 目:C語言
下一篇:理解C++編程中的std::function函數(shù)封裝
本文標(biāo)題:C語言中的函數(shù)指針學(xué)習(xí)筆記
本文地址:http://mengdiqiu.com.cn/a1/Cyuyan/2355.html
您可能感興趣的文章
- 04-02c語言函數(shù)調(diào)用后清空內(nèi)存 c語言調(diào)用函數(shù)刪除字符
- 04-02c語言的正則匹配函數(shù) c語言正則表達(dá)式函數(shù)庫
- 04-02func函數(shù)+在C語言 func函數(shù)在c語言中
- 04-02c語言中對(duì)數(shù)函數(shù)的表達(dá)式 c語言中對(duì)數(shù)怎么表達(dá)
- 04-02c語言用函數(shù)寫分段 用c語言表示分段函數(shù)
- 04-02c語言編寫函數(shù)冒泡排序 c語言冒泡排序法函數(shù)
- 04-02c語言沒有round函數(shù) round c語言
- 04-02c語言分段函數(shù)怎么求 用c語言求分段函數(shù)
- 04-02C語言中怎么打出三角函數(shù) c語言中怎么打出三角函數(shù)的值
- 04-02c語言調(diào)用函數(shù)求fibo C語言調(diào)用函數(shù)求階乘


閱讀排行
本欄相關(guān)
- 04-02c語言函數(shù)調(diào)用后清空內(nèi)存 c語言調(diào)用
- 04-02func函數(shù)+在C語言 func函數(shù)在c語言中
- 04-02c語言的正則匹配函數(shù) c語言正則表達(dá)
- 04-02c語言用函數(shù)寫分段 用c語言表示分段
- 04-02c語言中對(duì)數(shù)函數(shù)的表達(dá)式 c語言中對(duì)
- 04-02c語言編寫函數(shù)冒泡排序 c語言冒泡排
- 04-02c語言沒有round函數(shù) round c語言
- 04-02c語言分段函數(shù)怎么求 用c語言求分段
- 04-02C語言中怎么打出三角函數(shù) c語言中怎
- 04-02c語言調(diào)用函數(shù)求fibo C語言調(diào)用函數(shù)求
隨機(jī)閱讀
- 01-10SublimeText編譯C開發(fā)環(huán)境設(shè)置
- 01-11ajax實(shí)現(xiàn)頁面的局部加載
- 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文
- 08-05dedecms(織夢)副欄目數(shù)量限制代碼修改
- 01-10delphi制作wav文件的方法
- 04-02jquery與jsp,用jquery
- 01-10C#中split用法實(shí)例總結(jié)
- 01-10使用C語言求解撲克牌的順子及n個(gè)骰子
- 08-05織夢dedecms什么時(shí)候用欄目交叉功能?
- 08-05DEDE織夢data目錄下的sessions文件夾有什