日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

C/C++函数指针

發(fā)布時間:2024/2/28 c/c++ 50 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C/C++函数指针 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

函數(shù)指針

與數(shù)據(jù)項相似,函數(shù)也有地址。函數(shù)的地址是存儲其機器語言代碼的內(nèi)存的開始地址。我們可以編寫將另一個函數(shù)的地址作為參數(shù)的函數(shù)。這樣第一個函數(shù)將能夠找到第二個函數(shù),并運行它。與直接調(diào)用一個函數(shù)相比,這種方法比較笨拙,但它允許在不同的時間傳遞不同函數(shù)的地址,這意味著可以在不同的時間使用不同的函數(shù)。

?

(1)獲取函數(shù)的地址

獲取函數(shù)的地址很簡單:只要使用函數(shù)名即可(后面不跟參數(shù))。也就是說,如果think()是一個函數(shù),則think就是該函數(shù)的地址。要將函數(shù)作為參數(shù)進行傳遞,必須傳遞函數(shù)名。一定要區(qū)分傳遞的是函數(shù)的地址還是函數(shù)的返回值:

Process(think); ????//傳遞函數(shù)的地址 Process(think()); ??//傳遞函數(shù)的返回值

?

(2)聲明函數(shù)指針

聲明指向某種數(shù)據(jù)類型的指針時,必須指定指針指向的類型。同樣,聲明指向函數(shù)的指針時,也必須指定指針指向的函數(shù)類型。這意味著聲明應(yīng)指定函數(shù)的返回類型以及函數(shù)的特征標(biāo)(參數(shù)列表)。也就是說,聲明應(yīng)像函數(shù)原型那樣指出有關(guān)函數(shù)的信息。例如一個函數(shù)原型如下:

double asd(int);

則正確的指針類型聲明如下:

double (*pf)(int); ??//pf指向使用一個參數(shù)并返回double類型數(shù)據(jù)的函數(shù)正確地聲明pf后,便可以將相應(yīng)函數(shù)的地址賦給它: double asd(int); double (*pf)(int); pf = asd; ??????????//asd是函數(shù),因此(*pf)也是函數(shù)

asd()的特征標(biāo)和返回類型必須與pf相同。????

?

(3)使用指針來調(diào)用函數(shù)

(*pf)扮演的角色和函數(shù)名相同,因此使用(*pf)時,只需將它看作函數(shù)名即可:

double asd(int); double (*pf)(int); pf = asd; ?????????? //asd是函數(shù),因此(*pf)也是函數(shù) double x = asd(4); double y = (*pf)(5);實際上,C++也允許像使用函數(shù)名那樣使用pf: double y = pf(5);

第一種格式雖然不好看,但它給出了強有力的提示——代碼正在使用函數(shù)指針。

?

為何pf和(*pf)等價?一方認為,由于pf是函數(shù)指針,而*pf是函數(shù),因此應(yīng)將(*pf)用作函數(shù)調(diào)用。另一方認為,由于函數(shù)名是指向該函數(shù)的指針,指向函數(shù)的指針的行為應(yīng)與函數(shù)名相似,因此應(yīng)將pf()用作函數(shù)調(diào)用使用。C++進行了折衷,這兩種方式都允許。

?

(4)函數(shù)指針實例

#include <iostream> using namespace std;double betsy(int); double pam(int); void estimate(int lines, double (*pf)(int));int main() {int code;cout << "How many lines of code do you need? ";cin >> code;cout << "Here's Bets's estimate:\n";estimate(code, betsy);cout << "Here's Pam's estimate:\n";estimate(code, pam);return 0; }double betsy(int lns) {return 0.05 * lns; }double pam(int lns) {return 0.03 * lns + 0.0004 * lns * lns; }void estimate(int lines, double (*pf)(int)) {cout << lines << " lines will take ";cout << (*pf)(lines) << " hour(s)\n"; }

?

深入探討函數(shù)指針

下面是一些函數(shù)的原型,它們的特征標(biāo)和返回類型相同:

const double *f1(cosnt double ar[], int n); const double *f1(cosnt double [], int n); const double *f1(cosnt double *, int n);

在函數(shù)原型中,參數(shù)列表cosnt double ar[]與cosnt double *ar的含義完全相同。其次,在函數(shù)原型中,可以省略標(biāo)識符。因此,cosnt double ar[]可簡化為cosnt double [],而cosnt double *ar可簡化為cosnt double *。

接下來,假設(shè)要聲明一個指針,它可以指向這三個函數(shù)之一。假定該指針名為pa,則只需要將目標(biāo)函數(shù)原型中的函數(shù)名替換為(*pa):

const double *(*pa)(const double *, int);

可在聲明的同時進行初始化:

const double *(*pa)(const double *, int) = f1;使用C++的自動類型推斷功能時,代碼要簡單的多: auto p2 = f2; ???

?

現(xiàn)在來分析下面的語句:

cout << (*p1)(asd, 3) << ": "?<< *(*p1)(asd, 3) <<endl; cout << p2(asd, 3) << ": "?<< *p2(asd, 3) <<endl;

根據(jù)前面的知識可知,(*p1)(asd, 3)和p2(asd, 3)都可以調(diào)用所指向的函數(shù)(本例中是f1()和f2()),并將asd和3作為參數(shù)。因此,顯示的是這兩個函數(shù)的返回值。返回值類型為const double *(即double值的地址),因此在每條cout語句中,前半部分顯示的都是一個double值的地址。為了查看存儲在這些地址處的實際值,需要將運算符*應(yīng)用于這些地址,如表達式*(*p1)(asd, 3)和*p2(asd, 3)。

若需要用到三個函數(shù),可以創(chuàng)建一個函數(shù)指針數(shù)組。這樣,將可使用for循環(huán)通過指針依次調(diào)用每個函數(shù)。這種聲明應(yīng)類似于單個函數(shù)指針的聲明,但必須在某個地方加上[3],以指出這是一個包含三個函數(shù)指針的數(shù)組。問題是在什么地方加上[3],答案如下:

const double *(*pa[3])(const double *, int) = {f1, f2, f3};

因為運算符[]的優(yōu)先級高于*,因此*pa[3]表明pa是一個包含3個指針的數(shù)組。

*pd[3] ?????//3個指針的數(shù)組 (*pd)[3] ???//一個指向包含3個元素數(shù)組的指針

?

上面創(chuàng)建的是函數(shù)指針的數(shù)組,還可以創(chuàng)建一個指向整個數(shù)組的指針。由于數(shù)組名pa是指向函數(shù)指針的指針,即所要創(chuàng)建的指針是指向指針的指針。使用單個值對其進行初始化,可以使用auto:

auto pc = &pa;

但為了更好理解函數(shù)指針,可以聲明pd指針,若它指向一個包含3個元素的數(shù)組,則聲明的核心部分是(*pd)[3]由pa的聲明描述可得pd的聲明如下:

const double *(*(*pd)[3])(const double *, int) = &pa;

聲明部分有3個*,看著就頭大,但仔細分析其實也沒有那么復(fù)雜。首先第一個*是告訴我們返回值是double*,而第三個*的意思是(*pd)[3]為一個指向包含3個元素數(shù)組的指針。第二個*的意思是創(chuàng)建了一個指向指針數(shù)組的指針。

要調(diào)用函數(shù),需要認識到這樣一點:既然pd指向數(shù)組,那么*pd就是數(shù)組,而(*pd)[i]是數(shù)組中的元素,即函數(shù)指針因此較為簡單的函數(shù)調(diào)用是(*pd)[i](asd, 3),而*(*pd)[i](asd, 3)是返回的指針指向的值。也可以使用第二種使用指針調(diào)用函數(shù)的方法(前面提到的pf(5)和(*pf)(5)):使用(* (*pd)[i] )(asd, 3)來調(diào)用函數(shù),*(* (*pd)[i] )(asd, 3)是指向的double值。當(dāng)看到*(*pd)[i](asd, 3)和(* (*pd)[i] )(asd, 3)可能有點混,但是這樣看可能就能感覺到不一樣了,*[(*pd)[i](asd, 3)](返回指向的值)?和{* (*pd)[i] }(asd, 3)(調(diào)用函數(shù))。這里可以將(*pd)[i]代換成函數(shù)名,沒有那么多*,理解能容易點。

因為涉及到了&pa,所以多提一點:pa(它是數(shù)組名,表示地址)和&pa之間的差別。從數(shù)字上說,pa和&pa的值相同,但它們的類型不同。一種差別是,pa+1為數(shù)組中下一個元素的地址,而&pa+1為數(shù)組pa后面一個12字節(jié)內(nèi)存塊的地址(假定地址為4字節(jié))。另一個差別是,要得到第一個元素的值,只需要對pa解除一次引用,而對&pa要解除兩次引用:

**&pa == *pa == pa[0]

?

實例代碼如下:

#include <iostream> using namespace std;const double *f1(const double ar[], int n); const double *f2(const double [], int n); const double *f3(const double *, int n);int main() {double asd[3] = {111.1, 222.2, 333.3};const double *(*p1)(const double *, int) = f1;const double *(*p2)(const double *, int) = f2;cout << "Using pointers to functions:\n";cout << "Address Value\n";cout << (*p1)(asd, 3) << ": " << *(*p1)(asd, 3) <<endl;cout << p2(asd, 3) << ": " << *p2(asd, 3) <<endl;const double *(*pa[3])(const double *, int) = {f1, f2, f3};cout << "\nUsing an array of pointers to functions:\n";cout << "Address Value\n";for(int i = 0; i < 3; i++)cout << pa[i](asd, 3) << ": " << *pa[i](asd, 3) <<endl;cout << "\nUsing a pointer to an array of pointers:\n";cout << "Address Value\n";const double *(*(*pc)[3])(const double *, int) = &pa;cout << (*pc)[0](asd, 3) << ": " << *(*pc)[0](asd, 3) <<endl;const double *(*(*pd)[3])(const double *, int) = &pa;const double *pdb = (*pd)[1](asd, 3);cout << pdb << ": " << *pdb <<endl;cout << (*(*pd)[2])(asd, 3) << ": " << *(*(*pd)[2])(asd, 3) <<endl;return 0; }const double *f1(const double *ar, int n) {return ar; }const double *f2(const double ar[], int n) {return ar+1; }const double *f3(const double ar[], int n) {return ar+2; }

總結(jié)

以上是生活随笔為你收集整理的C/C++函数指针的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。