距離我們的指針結束我的草稿應該還剩下1節,朋友們馬上就要結束了!!!
上次我們説到了,指針數組,字符指針,下面我們就要學習函數指針,這是非常重要的所以單獨寫的
1,函數指針
什麼是函數指針變量呢?
根據前⾯學習整型指針,數組指針的時候,我們的類⽐關係,我們不難得出結論:函數指針變量應該是⽤來存放函數地址的,未來通過地址能夠調⽤函數的。那麼函數是否有地址呢?
我們先來個代碼試試水,先寫應該簡單的加法函數
int add(int a, int b)
{
return a + b;
}
int main()
{
int a = 2;
int b = 9;
int c= add(a,b);
printf("%d\n",c);
return 0;
}
然後將我們的加法函數的地址看看能不能打印,
int add(int a, int b)
{
return a + b;
}
int main()
{
int a = 2;
int b = 9;
int c= add(a,b);
printf("%d\n",c);
printf("%p\n", add);
printf("%p\n", &add);
return 0;
}
我們可以發現,add的地址被我們打印出來了,同時我們將的到函數指針的地址即&add=add:取地址等於函數名字。
既然函數是有地址的那麼,如果我們要將函數的地址存放起來,就得創建函數指針變量咯,函數指針變量的寫法其實和數組指針差別不大,
4.1函數指針的寫法
int (*pa)(int , int)
int (*pa) (int x, int y)
| | |
| | |
| | pf3
指向函數的參數類型和個數的交代
|
函數指針變量名
pa
指向函數的返回類型
int (*) (int x, int y) //pa
函數指針變量的類型
我們可以使用我們的加法函數去驗證,是否有效
int add(int a, int b)
{
return a + b;
}
int main()
{
int a = 2;
int b = 9;
// int c= add(a,b);
int (*padd)(int, int) = add;
printf("%d\n",(*padd)(2,9));
printf("%d\n", padd(2, 9));
printf("%p\n", add);
printf("%p\n", &add);
return 0;
}
調用函數,我們是否想過居然我們將函數放到了函數指針裏面,那麼我們是否不需要使用*符號
#include<stdio.h>
int add(int x, int y)
{
return x + y;
}
int main()
{
int(*padd)(int ,int) = &add;
int num = add(3,5);
printf("%d\n", num);
int num1 = (*padd)(3,4);
printf("%d\n", num1);
int(*padd2)(int, int) = add; //
這裏我們不使用
&
,證明
&add==add
int num2 = (*padd2)(3, 4);
printf("%d\n", num2);
int num3 = padd2(3, 4);
printf("%d\n", num2);
}
函數的寫法在上面寫了,甚至在我們將函數方到我們的函數指針裏面,我們不需要使用add,而是使用函數指針就可以將我們的函數
直接調用起來,重點是在寫函數指針的時候不要忘了寫()裏面的類型,VS會報錯的哦:
來考驗你們了下面的代碼的函數指針應該怎麼寫,
int * test(int x, char y)
{
return NULL;
}
int main()
{
? =test;
}
4.2 兩段有趣的代碼
兩段有趣的代碼來自《c陷阱和缺陷》這本書,下面的代碼建議仔仔細細的看看
1,
(*(void (*)())0)();
我們來看看上面的代碼,先將括號分清這裏是這樣的( (void(*)())0 ) ()
然後我們先分析最裏面的void (*) ()
這是不是一個函數指針類型,為什麼説是類型因為像int (*P)()這樣才是一個函數指針的變量,沒有P是一種類型----------這是最裏面
接下來我們來看看(void()()0外面的()0是什麼,我們學習過強制類型轉換操作符()這裏也是一樣的使用方法是將整數強制類型轉換成地址,如果我們在外面方一個那麼他是不是解引用了所以*()0是解引用 ---void(*)()我將它省略了方便看
最後(*()0)()像不像函數指針(*padd)()是像的,所以最依舊是一個函數的調用
2
void (*signal(int , void(*)(int)))(int);
我們來看看上面的代碼, void ( *signal ( int , void( * ) (int) ) ) (int);
然後我們先分析最裏面的signal ( int , void( * ) (int) ) 是不是像一個函數signal函數的參數有兩個,一個是int 一個是函數指針,void( * ) (int)函數時參數int 返回類型是void
最外面的void () (int )是函數指針,指針指向的函數時參數是int 返回類型是void
4,3typedef關鍵字
這裏我們再見見我們的關鍵字typedef,不知道大家還記不記得這個關鍵字是用來幹嘛的》
可以將他簡單的理解為給太長的,不想寫的起個外號
拜拜下一節再見