官术网_书友最值得收藏!

第52章 指針(六)

  • 程序媛養成計劃
  • 任煦之秋
  • 2038字
  • 2020-05-24 23:47:30

「哦,曉得了。」

老爹說這些的確是現實中存在的問題,班上就有很多同學的家長不讓他們玩兒手機和電腦,說是會影響到學習。一方為了防止對方玩兒手機,另一方想突破對方的封鎖,于是雙方展開了一場場斗智斗勇,各有輸贏。

這大概就和老爹說的一樣吧,不能單純地從某個方面來看待這件事情。學習成績好的人有玩兒手機和電腦的,學習成績不好的也有不玩兒手機和電腦的,關鍵還是在于使用者如何使用吧。

當然了,一般來說小孩兒的自制能力比較差,這個時候就需要家長合理的管控了。毋庸置疑的是,老爹在這一點做得非常好。

「好了好了,閑話就說到這里,咱們還是繼續說函數和指針之間那點事兒。其實函數和指針的關系也挺簡單的,無非就三種情況:指針作為函數參數,函數返回值為指針。

其中指針作為函數參數又有兩種情況,第一是指針變量指向的是數據,如int、double以及結構體或者枚舉這種,還有一種特例,那就是指針變量指向的是一個函數,我們把一個函數A的指針作為參數傳給另一個函數B,這樣在函數B中就可以通過這個指針調用函數A了,這就是所謂的回調函數。

概念性的東西咱們就先說到這里,還是以實際的例子來說明吧。

首先說普通指針作為函數的參數,其實這種情況你們已經見識過了,我一開始說到的swap函數就是這樣了。我相信通過之前的講解,你們對這個函數的理解已經算是比較透徹了,這里我們就不再贅述。

所以我們接下來看看當指針作為一個函數的返回值的這種情況,比如說我們來實現一個函數,功能是把給定的字符串轉成大寫的,并把轉換后的字符串返回。

由于字符串是一個char*,正好滿足指針作為返回值。

typedef char* String;

String toUpperCase(String str)

{

const char delta ='A'-'a';

String temp = str;

while (*temp !='\0')

{

if ('a'<=*temp &&*temp <='z')

{

*temp =*temp + delta;

}

temp++;

}

return str;

}

因為我們已經給char*定義了一個String別名,所以我們在代碼中就使用它,比較利于閱讀理解。

在使用這個函數的時候,我們就能夠體會到char*和char[]的區別了。

String str =“hello world“;

String result = toUpperCase(str);

將會報錯,而

char[] str =“hello world“;

String result = toUpperCase(str);

卻能夠得到正確的結果,至于為什么會這樣,結合字符串是常量的概念,以你們現在的水品來說,應該是能夠明白這其中的道理的。」

老爹笑了笑。

「第一種情況str是一個指針,它直接指向了一個常量,而toUpperCase()卻試圖修改一個常量的值,所以在運行的時候報錯了。

但是第二種情況str是一個數組,沒有任何限制,在函數中temp獲取了這個數組的指針地址,然后對其修改,自然不會出任何問題。」

小弦子不愧是小弦子,我都還沒有來得及嘗試運行代碼,他居然憑空推算出來了結果,不佩服真的不行。

「嗯,不錯,的確是這樣。這就是指針作為返回值的用法,應該沒有什么難度吧?」

若是按照老爹例程代碼來看,好像確實沒有什么難度。

「不過返回一個指針,一定要確保這個指針是可用的,如果你返回的指針地址是函數中的一個局部變量,就可能引發不可預知的錯誤。

因為局部變量在函數執行結束后就被回收了,這時如果通過指針來訪問一個被釋放的了內存,會引發的后果是真的無法預料?!?

我和小弦子都深以為然地點了點頭,畢竟類似的問題老爹已經強調過好多遍了。

「好了,那我們就來講講最后一種情況,一個指針指向一個函數。先說如何定義一個函數指針:

返回值類型(*fp_name)(參數類型1,參數類型2……)

例如:

int (*fp)(int,int)

就聲明了一個函數指針變量,它可以指向返回值為int類型,參數列表為兩個int類型的所有函數。

int max(int a, int b)

{

return a > b ? a : b;

}

int min(int a, int b)

{

return a > b ? b : a;

}

比如說這里的max和min都符合條件,所以我們就可以這樣:

int (*fp_max)(int,int);

int (*fp_min)(int,int);

fp_max = max;

fp_min = min;

如果要使用函數指針來執行指向的函數,就需要這樣:

int maxValue =(*fp_max)(3,4);

int minValue =(*fp_min)(1,2);」

「看上去就好復雜的樣子……」

我皺著眉頭看著老爹幻燈片上敲出來的這些內容,突然覺得腦袋運轉都幾乎停滯了。

「既然如此,那我們就來解析一下。我們在聲明一個變量時,會使用int、

double等類型描述符,其本質在于告訴計算機這個變量的內存占用情況,以及讀寫時的規則。是這樣的吧?」

我和小弦子點了點了點頭。

「那么我們聲明這些變量的指針的時候,是不是也要聲明使用指針讀寫數據時的規則呢?」

「嗯嗯~」

「同樣的,我們在定義一個函數的時候,是不是要告訴計算機這個函數的返回值、參數列表?那么同樣的,我們聲明一個函數指針也要具備這些啊。

在聲明一個指針變量的時候我們是不是會用到『*』?」

「是的~」

「同理,函數指針它也是一個指針,那它憑哪樣搞特殊不使用『*』來自報家門,告訴計算機自己是一個指針變量呢?

再問,當我們要訪問一個指針的指向的地址中的內容是,會使用什么?」

「*」

「那不就結了么?那函數指針雖然指向的是一個函數,那么我們要訪問這個函數,不得也用『*』么?

按照這個思路,你們再去看看上面的代碼,是不是就能夠明白其中的含義了呢?」

「臥槽,有道理啊!」

還別說,經過老爹這么解釋,似乎還真的有那么一些道理。

「其實啊,這種格式看上去的確是麻煩,而且fp_max和fp_min除了指針名字不一樣之外,其它都完全一樣,這不是重復代碼么?所以我們得像個辦法把這個問題給解決了,不然以后我們要聲明很多類似函數指針的時候還不得累死。

要是后面再修改,比如說修改返回值類型,或者修改參數列表類型……」

主站蜘蛛池模板: 台前县| 青龙| 保定市| 南康市| 凉山| 娄烦县| 石狮市| 西乡县| 乌恰县| 朝阳县| 金华市| 彝良县| 阜新| 托里县| 晋州市| 扶余县| 赣榆县| 胶州市| 成武县| 临桂县| 永新县| 社会| 白银市| 卢龙县| 五指山市| 土默特左旗| 宁城县| 石景山区| 措美县| 韶山市| 房产| 宁乡县| 桦南县| 拉萨市| 文水县| 安庆市| 平安县| 凤阳县| 新兴县| 留坝县| 夏河县|