首页
/
每日頭條
/
生活
/
c語言指針函數使用方法
c語言指針函數使用方法
更新时间:2024-04-29 10:20:33

關于指針,前面文章C語言指針詳解有過介紹,這裡主要讨論函數指針和指針函數。

來自公衆号:C語言與cpp編程

c語言指針函數使用方法(CC函數指針與指針函數)1

1 什麼是指針?

定義:指針是程序數據在内存中的地址,而指針變量是用來保存這些地址的變量;

c語言指針函數使用方法(CC函數指針與指針函數)2

上面一個 4GB 的内存可以存放 2^32 字節的數據。左側連續的十六進制編号就是内存地址,每個内存地址對應一個字節的内存空間。而指針變量保存的就是這個編号,也即内存地址。

指針的聲明:

指針其實就是一個變量,指針的聲明方式與一般的變量聲明類似,如下:

int*p;//聲明一個int類型的指針p,該指針指向一個int類型的對象 char*p//聲明一個char類型的指針p,該指針指向一個int類型的對象 int*arr[10]//聲明一個指針數組,該數組有10個元素,其中每個元素都是一個指向int類型對象的指針 int(*arr)[10]//聲明一個數組指針,該指針指向一個int類型的一維數組 int**p;//聲明一個指針p,該指針指向一個int類型的指針

聲明一個指針變量并不會自動分配任何内存。在對指針進行間接訪問之前,指針必須進行初始化:或是使他指向現有的内存,或者給他動态分配内存,否則我們并不知道指針指向哪兒,這個問題需要特别關注。

2 什麼是函數指針?

函數指針定義:函數指針是指向函數的指針變量。 因此“函數指針”本身首先應是指針變量,隻不過該指針變量指向函數。這正如用指針變量可指向整型變量、字符型、數組一樣,這裡是指向函數。

其通用表達式為:類型說明符 (*函數名) (參數)

int(*fun)(intx)//函數指針的定義 int(*fun)(intx,inty)//函數指針的定義

函數指針在PC軟件開發中使用較少,在嵌入式行業使用較多,但是無論是PC軟件還是嵌入式軟件,理解函數指針的定義和使用,對于理解程序設計都是很有好處的。

函數指針的賦值

函數指針和其他指針一樣定義之後使用之前也是需要初始化。

函數指針有兩個用途:調用函數和做函數的參數

int(*fun)(intx,inty)//函數指針的定義 fun=&Function//函數指針的賦值方式1 fun=Function//函數指針的賦值方式2 x=(*fun)()//函數指針的調用方式1 x=fun()//函數指針的調用方式2

函數賦值的時候取地址運算符&不是必需的,因為一個函數标識符就表示了它的地址,并且賦值的時候函數不需要帶圓括号;

如果是函數調用,還必須包含一個圓括号括起來的參數表。

函數指針的用法

我們使用指針的時候,需要通過鑰匙 * 來取其指向的内存裡面的值,函數指針使用也如此。通過用(*pf)取出存在這個地址上的函數,然後調用它。

char*fun(char*p1,char*p2) { inti=0; i=strcmp(p1,p2); if(0==i) { returnp1; } else { returnp2; } } intmain() { char*(*pf)(char*p1,char*p2); pf=&fun; (*pf)("aa","bb"); return0; }

這裡需要注意到是,在Visual C 6.0裡,給函數指針賦值時,可以用&fun或直接用函數名fun。這是因為函數名被編譯之後其實就是一個地址,所以這裡兩種用法沒有本質的差别。

用法延申

當我們不滿足于函數指針上面如此簡單的用法時,這時候需要一個高級用法來擴展我們對于函數指針的認知邊界。

感興趣的同學可以看看下面這個用法,并嘗試理解該表達式是如何使用的函數指針。

(*(void(*)())0)();//出自《CTrapandPitfalls》這本經典的書

答案如下: ``

  • 第一步:通過void(*) (),可以明白這是一個函數指針類型。這個函數沒有參數,沒有返回值。
  • 第二步:通過(void(*) ())0,可以明白這是将0強制轉換為函數指針類型,0是一個地址,也就是說一個函數存在首地址為0的一段區域内。
  • 第三步:通過(*(void(*) ())0),可以明白這是取0地址開始的一段内存裡面的内容。
  • 第四步:最終理解(*(void(*) ())0)(),這是函數調用。
讓程序跳轉到絕對地址為0x0113F90C

方法一:

  • 将0x0113F90C地址強制轉換為函數指針類型,即: (void (*)())0x0113F90C
  • 然後調用:((void (*)())0x0113F90C)()

方法二:

typedef(void(*)())VoidFuncPtr; ((VoidFuncPtr)0x0113F90C)();

面試題:指出程序的錯誤

#include<stdio.h> voidmain(void) { intmax(x,y); int*p=max; inta,b,c,d; scanf("%d%d%d",a,b,c); d=p(p(a,b),c); printf("d:%d\n",d); return; } intmax(inta,inty) { return(x>y?x:y); }

答案

  • int max(x ,y);函數聲明錯誤,改為:int max(int x,int y);

解析:max函數聲明隻是寫出了函數的形參的名稱,這對參數的類型來說是毫無意義的,編譯器會把x和y當做數據類型來看,編譯時會出錯,max的調用肯定也會出錯。

  • int *p=max;指針定義錯誤,改為:int (*p)(int ,int)=max;

解析:函數的指針是不能直接賦值給int型指針.

  • scanf("%d %d %d",a,b,c);庫函數使用錯誤,改為scanf("%d %d%d",&a,&b,&c);

解析:庫函數使用錯誤,第二部分應該是接收數據的地址,這裡卻寫成了變量。

  • d=p(p(a,b),c);函數指針調用函數錯誤,改為d=(*p)((*p)(a,b),c); `

解析:用函數指針調用函數的格式如下:(【*】【函數指針名稱】)(【參數列表】);不能直接用函數指針加上參數就直接調用

3 什麼是指針函數?

指針函數定義:指針函數的落腳點是一個函數,這個函數的返回值是一個指針,與普通函數int function(int,int)類似,隻是返回的數據類型不一樣而已。

_type_*function(int,int)//返回的是指針地址 intfunction(int,int)//返回的是int型數據。

int*fun(intx)//指針函數的定義 int*fun(intx,inty)//指針函數的定義 int*fun(intx,inty)//指針函數的定義

以上三種寫法均正确,但是*靠近返回值一點更容易理解。

指針函數的調用

在調用指針函數時,需要一個同類型的指針來接收其函數的返回值。

typedefstruct_Data{ inta; intb; }Data; //指針函數 Data*f(inta,intb){ Data*data=newData; data->a=a; data->b=b; returndata; } intmain(intargc,char*argv[]) { QApplicationa(argc,argv); //調用指針函數 Data*myData=f(4,5); qDebug()<<"f(4,5)="<<myData->a<<myData->b; returna.exec(); }

不過也可以将其返回值定義為 void* 類型,在調用的時候強制轉換返回值為自己想要的類型。

其輸出結果是一樣的,不過不建議這麼使用,因為強制轉換可能會帶來風險。返回類型可以是任何基本類型和複合類型。返回指針的函數的用途十分廣泛。

事實上,每一個函數,即使它不帶有返回某種類型的指針,它本身都有一個入口地址,該地址相當于一個指針。

比如函數返回一個整型值,實際上也相當于返回一個指針變量的值,不過這時的變量是函數本身而已,而整個函數相當于一個“變量”。

4 函數指針和指針函數的區别

通過以上的介紹,小夥伴應該都能理解二者的定義。那麼簡單的總結下二者的區别:

1. 定義不同
  • 指針函數本質是一個函數,其返回值為指針。
  • 函數指針本質是一個指針,其指向一個函數。
2. 寫法不同
  • 指針函數:int* fun(int x,int y);
  • 函數指針:int (*fun)(int x,int y);

可以簡單粗暴的理解為,指針函數的*是屬于數據類型的,而函數指針的星号是屬于函數名的。

再簡單一點,可以這樣辨别兩者:函數名帶括号的就是函數指針,否則就是指針函數。

3. 用法不同

上面函數指針和指針函數的用法都有,但是函數指針的用法會更多,相對而言難度也更大,例如函數指針與回調函數,如果是C 非靜态成員函數指針,其用法也會有一些區别,感興趣的同學可以關注後續推文或自行查閱相關書籍。

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

,
Comments
Welcome to tft每日頭條 comments! Please keep conversations courteous and on-topic. To fosterproductive and respectful conversations, you may see comments from our Community Managers.
Sign up to post
Sort by
Show More Comments
推荐阅读
竹葉青高山綠茶價位
竹葉青高山綠茶價位
“羅馬不是一夜建成的”,品牌也同樣如此。隻有那些久經考驗的産品才能抵禦各種風險,逆勢生長成為一個影響久遠的偉大品牌。今年的新冠疫情,如同一塊“試金石”,檢驗着品牌的韌性與實力。品牌缺失是我國産業“大而不強”的軟肋,尤其在中國茶行業,長期面臨...
2024-04-29
逐個擊破成語故事
逐個擊破成語故事
兼聽則明,偏信則暗這個成語故事出自于漢·王符《潛夫論·明暗》:“國之所以治者君明也,其所以亂者君闇也。君之所以明者兼聽也,其所以闇者偏信也。是故人君通必兼聽,則聖日廣矣;庸說偏信,則愚日甚矣。詩雲:“先民有言,詢于刍荛。”兼聽則明,偏信則暗...
2024-04-29
野生動物糞便收集
野生動物糞便收集
對于很多90年代以前的農村娃來說,小昆蟲是童年的一大樂趣之一,畢竟那時候農村條件不是很好,基本上沒有錢買玩具來玩,所以農村娃們除了去摘些野草來玩以外,就是捉一些小昆蟲來玩,比如知了、螳螂、螞蚱、天牛、蝈蝈等,都是童年時常玩的小昆蟲。小昆蟲雖...
2024-04-29
泰國人最危險的菜
泰國人最危險的菜
說到吃,中國一定是世界上最種類豐富,吃法最多元,傳承最久遠的飲食文化大國之一,2012年5月首播的美食類紀錄片《舌尖上的中國》,可謂是酣暢淋漓的将中國各地的美食特色展現了出來,國人也因此系統的認識到了中國豐富飲食文化。今天要說的是一道曾經風...
2024-04-29
15種你需要了解的神奇動物
15種你需要了解的神奇動物
“感謝偉大的羅琳,讓我有了三個小時的快樂。現在一想到鄧布利多連死的時候都那麼孤獨,簡直要哭了。鄧布利多才是魔法世界裡最孤獨的英雄。”——豆瓣網友對于喜歡哈利·波特的影迷而言,霍爾沃茲的魔法世界一舉一動都是盛大的魔法狂歡,是專屬于每個哈迷的青...
2024-04-29
Copyright 2023-2024 - www.tftnews.com All Rights Reserved