2345網(wǎng)址大全的網(wǎng)址廣州:推動優(yōu)化防控措施落
目錄
函數(shù)指針
函數(shù)名和&函數(shù)名?
函數(shù)指針的定義
函數(shù)指針的使用
函數(shù)指針陷阱
代碼1
代碼2?
注意
函數(shù)指針數(shù)組定義
函數(shù)指針數(shù)組的使用?
指向函數(shù)指針數(shù)組的指針
書寫?
終于軍訓(xùn)圓滿結(jié)束了,首先回顧一下指針進(jìn)階篇(1)主要是指針&數(shù)組的點(diǎn)!
C語言之指針進(jìn)階篇(1)_唐棣棣的博客-CSDN博客https://blog.csdn.net/m0_74841364/article/details/132223126?spm=1001.2014.3001.5502今天我們繼續(xù)更深入的來了解指針!主要是指針&函數(shù)&數(shù)組的點(diǎn)!
函數(shù)指針
在前面我們已經(jīng)了解過字符指針,數(shù)組指針,這里我們將介紹到函數(shù)指針!
指針數(shù)組——是數(shù)組,是存放指針的數(shù)組。
數(shù)組指針——是指針,指向數(shù)組的指針。
字符指針——指向字符的指針。
整型指針——指向整型的指針。
浮點(diǎn)型的指針——指向浮點(diǎn)型的指針。
函數(shù)指針——指向函數(shù)的指針。
函數(shù)名和&函數(shù)名?
類比數(shù)組指針。
數(shù)組指針——指向數(shù)組的指針——存放的是數(shù)組的地址——&數(shù)組名就是數(shù)組的地址
函數(shù)指針——指向函數(shù)的指針——存放的是函數(shù)的地址——函數(shù)地址是否是&函數(shù)名呢??
那我們用代碼來驗(yàn)證下。?
#include<stdio.h>
int Add(int x, int y)
{return x + y;
}
int main()
{//int x = 0;//int y = 0;//scanf("%d %d", x, y);printf("%p\n", &Add);printf("%p\n", Add);//&函數(shù)名 就是函數(shù)的地址//函數(shù)名 也是函數(shù)的地址//注意函數(shù)名并沒有首元素這一說法
}
?&函數(shù)名和函數(shù)名,都是函數(shù)的地址。
那它們是否有什么區(qū)別和它們的類型是一樣的嗎?
它們沒有區(qū)別,知識寫法不一樣。
它們兩個(gè)類型是一樣的。指向同一個(gè)函數(shù),類型是相同的。
整形函數(shù)指針類型?
函數(shù)指針的定義
如果在程序中定義了一個(gè)函數(shù),那么在編譯時(shí)系統(tǒng)就會為這個(gè)函數(shù)代碼分配一段存儲空間,這段存儲空間的首地址稱為這個(gè)函數(shù)的地址。而且函數(shù)名和&函數(shù)名均表示的就是這個(gè)地址。既然是地址我們就可以定義一個(gè)指針變量來存放,這個(gè)指針變量就叫作函數(shù)指針變量,簡稱函數(shù)指針。
?那該怎樣去寫函數(shù)指針呢?
#include<stdio.h>
int Add(int x, int y)
{return x + y;
}
int main()
{printf("%p\n", &Add);printf("%p\n", Add);int (*p)(int,int) = &Add;//更容易理解和熟悉int (*p)(int x,int y) = &Add;int (*p)(int x,int y) = Add;//寫不寫x y都可int (*p)(int,int) = Add;
//&和x y 寫不寫都可
}
這個(gè)語句就定義了一個(gè)指向函數(shù)的指針變量 p。
首先它是一個(gè)指針變量,所以要有一個(gè)“*”,即(*p);
其次前面的 int 表示這個(gè)指針變量可以指向返回值類型為 int 型的函數(shù);
后面括號中的兩個(gè) int 表示這個(gè)指針變量可以指向有兩個(gè)參數(shù)且都是 int 型的函數(shù)。
所以合起來這個(gè)語句的意思就是:
定義了一個(gè)指針變量 p,該指針變量可以指向返回值類型為 int 型,且有兩個(gè)整型參數(shù)的函數(shù)。
p 的類型為 int(*)(int,int)。
int (*p) (int, int);
函數(shù)返回值類型 (* 指針變量名) (函數(shù)參數(shù)列表);
定義了一個(gè)指針變量 p,該指針變量可以指向返回值類型為 int 型,且有兩個(gè)整型參數(shù)的函數(shù)。p 的類型為 int(*)(int,int)。
p就是函數(shù)指針變量。
?那如果寫成int* p(int,int);?
*和int 結(jié)合 int* 變成了函數(shù)聲明了。?
函數(shù)指針的使用
函數(shù)指針的使用最長應(yīng)用在轉(zhuǎn)移表和回調(diào)函數(shù)??,那我們在接下來的文章都會講到。
#include<stdio.h>
int Add(int x, int y)
{return x + y;
}
int main()
{printf("%p\n", &Add);printf("%p\n", Add);int (*p)(int,int) = &Add;int ret=(*p)(3, 5);//解引用找到函數(shù)int ret = (********p)(3, 5);//*是個(gè)擺設(shè),寫不寫都可int ret = Add(3, 5);//直接調(diào)用Add函數(shù)就是用Add函數(shù)的地址int ret = p(3, 5);//這里也可以直接使用地址printf("%d", ret);
}
我們有以上三種寫法去調(diào)用函數(shù) Add,但是我們不可以亂寫哦!
int ret=* p(3, 5);
函數(shù)指針陷阱
閱讀兩段有趣的代碼!
我們改怎樣去理解這兩端代碼呢?
代碼1
(*(void (*)())0)();
//函數(shù)調(diào)用
圖錯(cuò)誤待修改??
- 在調(diào)用 0地址處的函數(shù),這個(gè)函數(shù)沒有參數(shù),返回類型是void
- 把0從int類型強(qiáng)制轉(zhuǎn)化成函數(shù)指針類型,指向了0處的地址處的函數(shù)
代碼2?
void (*signal(int , void(*)(int)))(int);
//函數(shù)聲明
圖錯(cuò)誤待修改?
- 這個(gè)代碼是一次函數(shù)聲明,聲明的是signal函數(shù)
- signal函數(shù)有兩個(gè)參數(shù),一個(gè)是int類型,一個(gè)是函數(shù)指針類型,該類型是void (*)(int)
- 函數(shù)指針類型 該函數(shù)指針指向的函數(shù),參數(shù)是int, 返回類型是void
- signal函數(shù)的返回類型也是函數(shù)指針類型,該類型是void (*) (int)
- 函數(shù)指針類型 該函數(shù)指針指向的函數(shù),參數(shù)是int, 返回類型是void
代碼2太復(fù)雜了,那能不能簡化代碼2???當(dāng)然可以。
void (* signal(int, void(*)(int)))(int);
//void(*)(int) signal(int void(*)(int));?
//重定義
typedef void(*pfun_t)(int);
pfun_t signal(int pfun_t);
注 :推薦《C陷阱和缺陷》
注意
- 函數(shù)指針變量&函數(shù)指針&函數(shù)指針類型
- 函數(shù)指針類型 修飾一個(gè) 函數(shù)指針變量(可以是函數(shù)等 / 也可以沒有/或者 將其他類型強(qiáng)制轉(zhuǎn)化成函數(shù)指針類型) 意味著則該函數(shù)指針指向一個(gè) 返回類型是,參數(shù)是的函數(shù)
- 函數(shù)指針定義
int(*p)(int,int)=Add;
- 函數(shù)指針調(diào)用
(*p)(3,5); p(3,5); (*p)(); p();//不傳參數(shù)
- 函數(shù)指針聲明
void (* signal(int,int))(int);
- 函數(shù)指針類型和函數(shù)指針變量的寫法
int(*p)(int,int); void(*p)(int);
函數(shù)指針數(shù)組定義
char * arr[5]字符指針數(shù)組——數(shù)組——存放的是字符指針
int * arr[5]整形指針數(shù)組——數(shù)組——存放的是整形指針
int(*p[5])(int,int)? ?void(*p[5])(int,char)等等
函數(shù)指針數(shù)組——數(shù)組——存放的是函數(shù)指針(函數(shù)的地址)
把函數(shù)的地址存到一個(gè)數(shù)組中,那這個(gè)數(shù)組就叫函數(shù)指針數(shù)組,那函數(shù)指針的數(shù)組如何定義呢?
int (*parr1[10]])();
int *parr2[10]();
int (*)() parr3[10];
?答案是:parr1 parr1 先和 [] 結(jié)合,說明parr1是數(shù)組。
? ? ? ? ? ? ? ?數(shù)組的內(nèi)容是什么呢? 是 int (*)() 類型的函數(shù)指針。
#include<stdio.h>
int Add(int x, int y)
{return x + y;
}
int Sub(int x, int y)
{return x - y;
}
int main()
{int(*p1)(int, int) = &Add;int(*p1)(int, int) = ⋐//函數(shù)指針數(shù)組中存放的類型相同的多個(gè)元素int(*p[])(int, int) = { &Add,&Sub };//p是函數(shù)指針數(shù)組_存放函數(shù)指針的數(shù)組//均是返回類型為int,函數(shù)參數(shù)是int,int類型
}
函數(shù)指針數(shù)組的使用?
函數(shù)指針數(shù)組的用途:轉(zhuǎn)移表。
使用條件:函數(shù)類型/函數(shù)參數(shù)類型必須一摸一樣
#define _CRT_SECURE_NO_WARNINGS 1
//計(jì)算器
#include<stdio.h>
void meau()
{printf("**************************\n");printf("** 1.add 2.sub ****\n");printf("** 3.mul 4.div ****\n");printf("** 0.exit *****\n");printf("**************************\n");
}
int Add(int x, int y)
{return x + y;
}
int Sub(int x, int y)
{return x - y;
}
int Mul(int x, int y)
{return x * y;
}
int Div(int x, int y)
{return x / y;
}
int main()
{int input = 0;int x = 0;int y = 0;int ret = 0;do{meau();printf("請選擇>");scanf("%d", &input);switch (input){case 1:printf("請輸入2個(gè)操作數(shù):");scanf("%d %d", &x, &y);ret = Add(x, y);printf("ret=%d\n", ret);break;case 2:printf("請輸入2個(gè)操作數(shù):");scanf("%d %d", &x, &y);ret = Sub(x, y);printf("ret=%d\n", ret);break;case 3:printf("請輸入2個(gè)操作數(shù):");scanf("%d %d", &x, &y);ret = Mul(x, y);printf("ret=%d\n", ret);break;case 4:printf("請輸入2個(gè)操作數(shù):");scanf("%d %d", &x, &y);ret = Div(x, y);printf("ret=%d\n", ret);break;case 0:printf("退出游戲");break;default:printf("選擇錯(cuò)誤,重新選擇\n");break;}} while (input);return 0;
}
能不能讓代碼變得簡單一點(diǎn)?
//簡化后
#include<stdio.h>
void meau()
{printf("**************************\n");printf("** 1.add 2.sub ****\n");printf("** 3.mul 4.div ****\n");printf("** 0.exit *****\n");printf("**************************\n");
}
int Add(int x, int y)
{return x + y;
}
int Sub(int x, int y)
{return x - y;
}
int Mul(int x, int y)
{return x * y;
}
int Div(int x, int y)
{return x / y;
}
int main()
{int input = 0;int x = 0;int y = 0;int ret = 0;//用函數(shù)指針數(shù)組//do{meau();printf("請選擇>\n");scanf("%d", &input);int(*p[])(int, int) = { NULL,&Add,&Sub,&Mul,&Div };//0 1 2 3 4if (input == 0)printf("退出游戲\n");else if (input > 0 && input <= 4){printf("請輸入兩個(gè)操作數(shù):\n");scanf("%d %d", &x, &y);ret = (*p[input])(x, y);printf("ret=%d\n", ret);// ret = p[input](x, y);//用函數(shù)指針數(shù)組的下標(biāo)找到指向的函數(shù)}else//其他printf("選擇錯(cuò)誤,請重新選擇!\n");} while (input);return 0;
}
?
當(dāng)然出了使用函數(shù)指針數(shù)組去更高效的使用計(jì)算器,下章我們將使用回調(diào)函數(shù)去高效優(yōu)化計(jì)算器!
指向函數(shù)指針數(shù)組的指針
指向函數(shù)指針數(shù)組的指針是一個(gè) 指針 指針指向一個(gè) 數(shù)組 ,數(shù)組的元素都是 函數(shù)指針 。
指向整型指針數(shù)組的指針
#include<stdio.h>
int main()
{int a = 0;int b = 0;int c = 0;int* arr[] = { &a,&b,&c };//整形指針數(shù)組int* (*p)[3] = &arr;//p是指針,是指向整形指針數(shù)組的指針return 0;
}
函數(shù)指針數(shù)組的指針
#include<stdio.h>
int main()
{int(*arr[5])(int, int) = { NULL,&Add,&Sub,&Mul,&Div };p = &arr;//存放函數(shù)指針數(shù)組的指針int(*(*p)[5])(int, int) = &arr;return 0;
}
書寫?
無論是函數(shù)指針&函數(shù)指針數(shù)組&函數(shù)指針數(shù)組的指針等等,可以一直延申下去!
我們在書寫變量是,首先將變量p寫出來,在添加其類型。
也可以從簡單的函數(shù)指針的基礎(chǔ)上修改!
?????最后,感謝大家的閱讀,若有錯(cuò)誤和不足,歡迎指正!最近的心情多做事少說話。
代碼------→【gitee:https://gitee.com/TSQXG】
聯(lián)系------→【郵箱:2784139418@qq.com】