C語言超詳細(xì)講解指向函數(shù)的指針
一、函數(shù)的指針
首先,函數(shù)名代表函數(shù)的起始地址,調(diào)用函數(shù)時(shí),程序會從函數(shù)名獲取到函數(shù)起始地址,并從該地址起執(zhí)行函數(shù)中的代碼,函數(shù)名就是函數(shù)的指針,所以我們可以定義一個(gè)指向函數(shù)的指針變量,用來存放函數(shù)的起始地址,這樣一來,就可以通過該變量來調(diào)用其所指向的函數(shù)。
二、指向函數(shù)的指針變量
定義指向函數(shù)的指針變量
返回值類型(* 指針變量名)(形參類型列表);
例如:int(*p)(int, int);,這行代碼定義了一個(gè)可以指向返回值為整型且有兩個(gè)整型形參函數(shù)的指針變量p,符合返回值為整型且有兩個(gè)整型形參的函數(shù)都可以將其地址(即其函數(shù)名)賦給p。
使用指向函數(shù)的指針變量
在使用指向函數(shù)的指針變量時(shí),只需要將函數(shù)名賦給指向函數(shù)的指針變量即可,因?yàn)楹瘮?shù)名就是該函數(shù)的入口地址。
由于指向函數(shù)的指針變量保存了函數(shù)的地址,則該指針變量就指向了對應(yīng)的函數(shù)。例如,求最大值的函數(shù)命名為max,如果將其函數(shù)名賦給指向函數(shù)的指針變量p(即p = max)后,則p就指向了max函數(shù),并且可以通過(*p)(a, b);的方式來調(diào)用max函數(shù),因?yàn)橹羔樧兞?code>p保存了max函數(shù)的地址,那么*p就是max。需要注意的是,其中*p前的*可以省略,故也可以寫成p(a, b);
三、調(diào)用函數(shù)的兩種方式
引例:自定義max函數(shù),求整數(shù)a和b中的較大者并返回給主調(diào)函數(shù),不考慮兩數(shù)相等的情況通過函數(shù)名調(diào)用函數(shù)
#include <stdio.h>
int max(int, int); // max函數(shù)的函數(shù)聲明
int main()
{
int a, b;
printf("請輸入兩個(gè)整數(shù):");
scanf("%d%d", &a, &b);
printf("兩數(shù)中的較大者的值為%d\n", max(a, b));
return 0;
}
int max(int a, int b)
{
if (a > b)
return a;
else
return b;
}通過指向函數(shù)的指針變量調(diào)用函數(shù)
#include <stdio.h>
int max(int, int); // max函數(shù)的函數(shù)聲明
int main()
{
int a, b;
int(*p)(int, int); // 定義指向函數(shù)的指針p
p = max; // p指向max函數(shù)
printf("請輸入兩個(gè)整數(shù):");
scanf("%d%d", &a, &b);
printf("兩數(shù)中的較大者的值為%d\n", (*p)(a, b)); // (*p)(a, b) 也可寫為 p(a, b)
return 0;
}
int max(int a, int b)
{
if (a > b)
return a;
else
return b;
}四、指向函數(shù)的指針的作用
看到這里有人可能會問,既然函數(shù)名就可以調(diào)用函數(shù),為什么還要弄個(gè)奇奇怪怪的指針?這難道不是多此一舉嘛?難倒是為了裝13?不管怎樣,使用指向函數(shù)的指針來調(diào)用函數(shù)肯定不是為了裝13,主要的原因是:用函數(shù)名調(diào)用函數(shù)時(shí)比較死板,只能調(diào)用所指定的一個(gè)函數(shù),而通過指針變量調(diào)用函數(shù)會比較靈活,可以根據(jù)不同的情況調(diào)用不同的函數(shù)。以下面的程序?yàn)槔?輸入兩個(gè)整數(shù),然后讓用戶選擇1或2,選1則調(diào)用max函數(shù)求出兩個(gè)整數(shù)的較大者并將其輸出,選2則調(diào)用min函數(shù)求出兩個(gè)整數(shù)的較小者并將其輸出,不考慮兩數(shù)相等的情況
#include <stdio.h>
int max(int, int); // max函數(shù)的函數(shù)聲明
int min(int, int); // min函數(shù)的函數(shù)聲明
int main()
{
int a, b, c, n;
int (*p)(int, int); // 定義指向函數(shù)的指針p
p = NULL; // 先將p賦為空
printf("請輸入兩個(gè)整數(shù):");
scanf("%d%d", &a, &b);
printf("輸入1獲取兩個(gè)數(shù)中的較大者,輸入2獲取兩個(gè)數(shù)中的較小者,請輸入:");
scanf("%d", &n);
if (n == 1)
p = max; // p指向max函數(shù)
else if (n == 2)
p = min; // p指向min函數(shù)
c = p(a, b); // 調(diào)用p所指向的函數(shù)
if (n == 1)
printf("兩個(gè)數(shù)中的較大者為:%d\n", c);
else
printf("兩個(gè)數(shù)中的較小者為:%d\n", c);
return 0;
}
int max(int a, int b)
{
if (a > b)
return a;
else
return b;
}
int min(int a, int b)
{
if (a < b)
return a;
else
return b;
}五、用指向函數(shù)的指針作函數(shù)參數(shù)(重點(diǎn))
指向函數(shù)的指針變量的一個(gè)重要用途是把函數(shù)的入口地址作為實(shí)參傳遞給其他函數(shù)。以下面的程序?yàn)槔?/p>
有兩個(gè)整數(shù)a和b,由用戶輸入1,2,3來決定進(jìn)行什么操作。輸入1則求出a和b中的較大者,輸入2則求出a和b中的較小者,輸入3則求出a與b之和,不考慮兩個(gè)數(shù)相等的情況
#include <stdio.h>
int fun(int, int, int (*p)(int, int));
int max(int, int);
int min(int, int);
int sum(int, int);
int main()
{
int a = 34, b = -21, n;
printf("輸入1獲得兩數(shù)中的較大者,輸入2獲得兩數(shù)中的較小者,輸入3獲得兩個(gè)數(shù)的和,請輸入:");
scanf("%d", &n);
if (n == 1)
printf("兩數(shù)中的較大者為%d\n", fun(a, b, max));
// 向fun函數(shù)中傳參時(shí),只需要傳入兩個(gè)整數(shù)或整型變量以及想要在fun函數(shù)內(nèi)執(zhí)行的函數(shù)的函數(shù)名即可
// 函數(shù)名會傳遞給對應(yīng)的形參指針變量
else if (n == 2)
printf("兩數(shù)中的較小者為%d\n", fun(a, b, min));
else if (n == 3)
printf("兩個(gè)數(shù)的和為%d\n", fun(a, b, sum));
return 0;
}
// fun函數(shù)的作用是獲取最終結(jié)果
int fun(int x, int y, int (*p)(int, int))
{
int result;
result = p(x, y); // 用result接收最終結(jié)果,不管執(zhí)行max,min,sum中的哪個(gè)函數(shù),fun函數(shù)內(nèi)部代碼都不用改變
return result;
}
int max(int x, int y)
{
if (x > y)
return x;
else
return y;
}
int min(int x, int y)
{
if (x < y)
return x;
else
return y;
}
int sum(int x, int y)
{
return x + y;
}從上面的程序中可以清晰地看出,不管調(diào)用max,min,sum中的哪個(gè)函數(shù),fun函數(shù)均沒有任何變化,在fun函數(shù)內(nèi)部的result只用來獲取結(jié)果并將結(jié)果返回,但不去判斷到底要通過哪個(gè)函數(shù)來計(jì)算這一結(jié)果,主調(diào)函數(shù)向其傳入哪個(gè)函數(shù),其內(nèi)部就執(zhí)行哪個(gè)函數(shù)。max,min,sum函數(shù)用來計(jì)算,fun函數(shù)用來獲取結(jié)果,這體現(xiàn)出了整個(gè)程序的模塊化。
六、為什么要將指向函數(shù)的指針變量作為函數(shù)的形參(重點(diǎn))
舉一個(gè)例子,我們在學(xué)習(xí)數(shù)組的過程中,想要把數(shù)組中的所有元素輸出,通常會接觸一個(gè)新詞,遍歷。其實(shí)遍歷的含義并不是將一個(gè)結(jié)構(gòu)中的元素輸出的過程,然而我在初學(xué)時(shí)便認(rèn)為遍歷等同于輸出,這是我在初學(xué)時(shí)對遍歷這個(gè)詞不準(zhǔn)確的理解,我相信也一定有人跟我一樣這樣認(rèn)為。其實(shí)遍歷指的是依次訪問某種結(jié)構(gòu)中的所有元素,至于對這些元素怎么操作,由程序員自己決定,比如,你想輸出所有的元素,那就可以調(diào)用輸出函數(shù)將每次獲取到的元素輸出;你想將所有元素的值翻倍,那就調(diào)用對應(yīng)的翻倍函數(shù)將每次獲取到的元素翻倍。但是這樣一來,遍歷函數(shù)的功能就變得十分單一,只能進(jìn)行一種操作,要么是遍歷并輸出,要么是遍歷并翻倍,如果在一個(gè)程序中,開始想要遍歷并翻倍,后又想要遍歷并輸出,就只能定義兩個(gè)函數(shù)來實(shí)現(xiàn),但是我們發(fā)現(xiàn)不管對元素怎么操作,訪問每個(gè)元素的代碼都是相同,并且只要想對結(jié)構(gòu)中的每個(gè)元素進(jìn)行操作,首先要做的就是訪問每個(gè)元素。但是如果為了輸出而定義一個(gè)先遍歷后輸出的函數(shù),為了將每個(gè)元素的值翻倍而定義一個(gè)先遍歷后翻倍的函數(shù),這樣遍歷元素的代碼就是重復(fù)的。那要怎么辦呢?既然遍歷的操作是重復(fù)的,那我們就定義一個(gè)專門的遍歷函數(shù),該函數(shù)只用來訪問元素,再定義其它多個(gè)操作數(shù)據(jù)的函數(shù),至于我們對遍歷后的數(shù)據(jù)執(zhí)行什么樣的操作,我們只需要將對應(yīng)的操作函數(shù)通過遍歷函數(shù)的形參接收過來,這樣就可以實(shí)現(xiàn)在遍歷函數(shù)中根據(jù)不同情況執(zhí)行不同操作的目的,如此一來既體現(xiàn)出了程序設(shè)計(jì)的結(jié)構(gòu)化與模塊化,又減少了編程時(shí)的代碼量。
到此這篇關(guān)于C語言超詳細(xì)講解指向函數(shù)的指針的文章就介紹到這了,更多相關(guān)C語言指向函數(shù)的指針內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++獲取當(dāng)前系統(tǒng)時(shí)間的方法總結(jié)
這篇文章主要介紹了C++獲取當(dāng)前系統(tǒng)時(shí)間的方法,實(shí)例總結(jié)了四個(gè)獲取系統(tǒng)時(shí)間的方法,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2015-04-04
c++ priority_queue用法入門超詳細(xì)教程
priority_queue即優(yōu)先級隊(duì)列,它的使用場景很多,它底層是用大小根堆實(shí)現(xiàn)的,可以用log(n)的時(shí)間動(dòng)態(tài)地維護(hù)數(shù)據(jù)的有序性,這篇文章主要介紹了c++ priority_queue用法入門超詳細(xì)教程,需要的朋友可以參考下2023-12-12
C++之CNoTrackObject類和new delete操作符的重載實(shí)例
這篇文章主要介紹了C++之CNoTrackObject類和new delete操作符的重載實(shí)例,是C++程序設(shè)計(jì)中比較重要的概念,需要的朋友可以參考下2014-10-10
linux c程序中獲取shell腳本輸出的實(shí)現(xiàn)方法
以下是對在linux下c程序中獲取shell腳本輸出的實(shí)現(xiàn)方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友可以過來參考下2013-08-08
C/C++程序開發(fā)中實(shí)現(xiàn)信息隱藏的三種類型
這篇文章主要介紹了C/C++程序開發(fā)中實(shí)現(xiàn)信息隱藏的三種類型的相關(guān)資料,需要的朋友可以參考下2016-02-02

