1.函數指針變量的創建
在x86環境下:
我們發現:以函數是有地址的,函數名就是函數的地址,當然也可以通過& 函數名 的?式獲得函數的地址。
如果我們要將函數的地址存放起來,就得創建函數指針變量咯,函數指針變量的寫法其實和數組指針?常類似。如下:
函數指針類型解析:?
?
再加上一組:
發現pf的前面可以不帶*
2.兩段有趣的代碼
?
?? ?(*(void (*)())0)();
?? ?//解釋一下
?? ?// void (*)()—— 是函數指針類型
?? ?//(void (*)()) —— 括弧里面放類型就是強制轉換
?? ?//(void (*)())0 —— 將0強制轉換為 void (*)() 的函數指針類型
?? ?//這就意味著我們假設 0 地址處放著無參,返回類型是 void 的函數
?? ?//最終是調用 0 地址處放的這個函數
?void (* signal( int, void(*)(int) ) )(int);
// signal —— 函數名
// int —— 參數1
// void(*)(int) —— 參數2
// signal( int, void(*)(int) ) —— 其中少函數值的返回類型
// 而剩下的void ( )(int); —— 這就是返回類型
// 所以這段代碼本質是一個函數聲明
// 想表達的意思是:
// void (*)(int)signal( int, void(*)(int) )
// 注意像上一行這樣寫是會報錯的
// 只是想要表達這個意思而已
3.typedef關鍵字
typedef 是?來類型重命名的,可以將復雜的類型,簡單化。?如,你覺得unsigned int 寫起來不?便,如果能寫成 uint 就?便多了,那么我們可以使?:
如果是指針類型,能否重命名呢?其實也是可以的,?如,將int* 重命名為 ptr_t ,這樣寫:
但是對于數組指針和函數指針稍微有點區別:
?如我們有數組指針類型?int(*)[5]?,需要重命名為 parr_t ,那可以這樣寫:
注意:
// 新的類型名必須在 * 的右邊
函數指針類型的重命名也是?樣的,?如,將 void(*)(int)? 類型重命名為? pf_t? ,就可以這樣寫:
那么要簡化上述的代碼2,可以這樣寫:
typedef void(*pfun_t)(int);
pfun_t signal(int, pfun_t);
本篇文章中所用到的代碼如下:
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
//int Add(int x, int y)
//{
// return x + y;
//}
//int main()
//{
// printf("%p\n", Add);
// printf("%p\n", &Add);
// return 0;
//}//int Add(int x, int y)
//{
// return x + y;
//}
//
//int main()
//{
// //回憶一下數組指針
// //int arr[10] = { 0 };
// //int (*pa)[10] = &arr;
// //函數與數組類似
// int (* pf)(int, int) = &Add;
// //(int, int) 是因為(int x, int y)
// // int (* pf)是因為int Add
// //pf是專門用來存放函數地址的,pf 就是函數指針變量
// return 0;
//}//int Add(int x, int y)
//{
// return x + y;
//}
//
//int main()
//{
// int(*pf)(int, int) = Add;
//
// int c = Add(2, 3);
// //函數名調用
// printf("%d\n", c);
//
// int d = (*pf)(3, 4);
// //函數指針變量調用
// printf("%d\n", d);
//
// int e = (pf)(4, 5);
// //函數指針變量調用
// printf("%d\n", e);
//
// return 0;
//}看看有趣的代碼
//int main()
//{
// (*(void (*)())0)();
// //解釋一下
// // void (*)()—— 是函數指針類型
// //(void (*)()) —— 括弧里面放類型就是強制轉換
// //(void (*)())0 —— 將0強制轉換為 void (*)() 的函數指針類型
// //這就意味著我們假設 0 地址處放著無參,返回類型是 void 的函數
// //最終是調用 0 地址處放的這個函數
// return 0;
//}//void (* signal( int, void(*)(int) ) )(int);signal —— 函數名int —— 參數1void(*)(int) —— 參數2signal( int, void(*)(int) ) —— 其中少函數值的返回類型而剩下的void ( )(int); —— 這就是返回類型所以這段代碼本質是一個函數聲明想表達的意思是:void (*)(int)signal( int, void(*)(int) )注意像上一行這樣寫是會報錯的只是想要表達這個意思而已
//
//int main()
//{
//
// return 0;
//}