函數指針和指針函數用法和區別

原文鏈接:https://blog.csdn.net/luoyayun361/article/details/80428882

前言

函數指針和指針函數,在學習 C 語言的時候遇到這兩個東西簡直頭疼,當然還有更頭疼的,比如什麼函數指針函數、指針函數指針、數組指針、指針數組、函數指針數組等等,描述越長其定義就越複雜,當然理解起來就越難,特別是剛開始學習這門語言的童鞋,估計碰到這些東西就已經要崩潰了,然後好不容易死記硬背下來應付考試或者面試,然後過了幾天發現,又是根本不會用,也不知道該在哪些地方用,這就尷尬了。
今天這裏只講兩個相對簡單的,其實上面說那些太複雜的東西也真的很少用,即便是用了理解起來很麻煩,所以莫不如先深刻理解這兩個比較容易的,並且項目中比較常用到。

正文

先來看看兩者的定義以及說明。

指針函數

定義

指針函數,簡單的來說,就是一個返回指針的函數,其本質是一個函數,而該函數的返回值是一個指針。
聲明格式爲:*類型標識符 函數名(參數表)

這似乎並不難理解,再進一步描述一下。
看看下面這個函數聲明:

int fun(int x,int y);
  • 1

這種函數應該都很熟悉,其實就是一個函數,然後返回值是一個 int 類型,是一個數值。
接着看下面這個函數聲明:

int *fun(int x,int y);
  • 1

這和上面那個函數唯一的區別就是在函數名前面多了一個*號,而這個函數就是一個指針函數。其返回值是一個 int 類型的指針,是一個地址。

這樣描述應該很容易理解了,所謂的指針函數也沒什麼特別的,和普通函數對比不過就是其返回了一個指針(即地址值)而已。

指針函數的寫法

int *fun(int x,int y);
int * fun(int x,int y);
int* fun(int x,int y);
  • 1
  • 2
  • 3

這個寫法看個人習慣,其實如果*靠近返回值類型的話可能更容易理解其定義。

示例

(由於本人習慣於 Qt 中進行開發,所以這裏爲了方便,示例是在 Qt 工程中寫的,其語法是一樣的,只是輸出方式不同)
來看一個非常簡單的示例:

typedef struct _Data{
    int a;
    int b;
}Data;

//指針函數
Data* f(int a,int b){
Data * data = new Data;
data->a = a;
data->b = b;
return data;
}

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
//調用指針函數
Data * myData = f(4,5);
qDebug() << "f(4,5) = " << myData->a << myData->b;

return a.exec();

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

輸出如下:

f(4,5) =  4 5
  • 1

注意:在調用指針函數時,需要一個同類型的指針來接收其函數的返回值。
不過也可以將其返回值定義爲 void*類型,在調用的時候強制轉換返回值爲自己想要的類型,如下:

//指針函數
void* f(int a,int b){
    Data * data = new Data;
    data->a = a;
    data->b = b;
    return data;
}

調用:
Data * myData = static_cast<Data*>(f(4,5));

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

其輸出結果是一樣的,不過不建議這麼使用,因爲強制轉換可能會帶來風險。

函數指針

定義

函數指針,其本質是一個指針變量,該指針指向這個函數。總結來說,函數指針就是指向函數的指針。
聲明格式:類型說明符 (*函數名) (參數)
如下:

int (*fun)(int x,int y);
  • 1

函數指針是需要把一個函數的地址賦值給它,有兩種寫法:

fun = &Function;
fun = Function;
  • 1
  • 2

取地址運算符&不是必需的,因爲一個函數標識符就表示了它的地址,如果是函數調用,還必須包含一個圓括號括起來的參數表。

調用函數指針的方式也有兩種:

x = (*fun)();
x = fun();
  • 1
  • 2

兩種方式均可,其中第二種看上去和普通的函數調用沒啥區別,如果可以的話,建議使用第一種,因爲可以清楚的指明這是通過指針的方式來調用函數。當然,也要看個人習慣,如果理解其定義,隨便怎麼用都行啦。

示例

int add(int x,int y){
    return x+y;
}
int sub(int x,int y){
    return x-y;
}
//函數指針
int (*fun)(int x,int y);

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
//第一種寫法
fun = add;
qDebug() << "(*fun)(1,2) = " << (*fun)(1,2) ;
//第二種寫法
fun = &sub;
qDebug() << "(*fun)(5,3) = " << (*fun)(5,3) << fun(5,3);

return a.exec();

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

輸出如下:

(*fun)(1,2) =  3
(*fun)(5,2) =  2 2
  • 1
  • 2

上面說到的幾種賦值和調用方式我都分別使用了,其輸出結果是一樣的。

二者區別

通過以上的介紹,應該都能清楚的理解其二者的定義。那麼簡單的總結下二者的區別:
###定義不同
指針函數本質是一個函數,其返回值爲指針。
函數指針本質是一個指針,其指向一個函數。

寫法不同

指針函數:int* fun(int x,int y);
函數指針:int (*fun)(int x,int y);
可以簡單粗暴的理解爲,指針函數的*是屬於數據類型的,而函數指針的星號是屬於函數名的。
再簡單一點,可以這樣辨別兩者:函數名帶括號的就是函數指針,否則就是指針函數。

用法不同

上面已經寫了詳細示例,這裏就不在囉嗦了。

總而言之,這兩個東西很容易搞混淆,一定要深入理解其兩者定義和區別,避免犯錯。

                                </div>
            <link href="https://csdnimg.cn/release/phoenix/mdeditor/markdown_views-e44c3c0e64.css" rel="stylesheet">
                </div>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章