【C語言】14-返回指針的函數與指向函數的指針


說明:這個C語言專題,是學習iOS開發的前奏。也為了讓有面向對象語言開發經驗的程序員,能夠快速上手C語言。如果你還沒有編程經驗,或者對C語言、iOS開發不感興趣,請忽略

前言

前面我們花了接近3個章節學習指針,應該都感受到指針的強大了吧。指針可以根據地址直接操作內存中的數據,使用得當的話,不僅能使代碼量變少,還能優化內存管理、提升程序性能。關於指針的內容還非常多,比如指針數組、指向數組的指針、指向指針的指針,呵呵,看到這些名字是否都覺得頭大了,不過我就暫時不在博客中講解這些內容了,我只講述在iOS開發中指針的最常見用法,比如這一章的內容----返回指針的函數指向函數的指針

 

一、返回指針的函數

 指針也是C語言中的一種數據類型,因此一個函數的返回值肯定可以是指針類型的。

返回指針的函數的一般形式為:類型名 * 函數名(參數列表)

 比如下面這個函數,返回一個指向char類型變量的指針

 1 // 將字符串str中的小寫字母變成大寫字母,並返回改變后的字符串
 2 // 注意的是:這里的參數要傳字符串變量,不能傳字符串常量
 3 char * upper(char *str) {
 4     // 先保留最初的地址。因為等會str指向的位置會變來變去的。
 5     char *dest = str;
 6     
 7     // 如果還不是空字符
 8     while (*str != '\0') {
 9         // 如果是小寫字母
10         if (*str >= 'a' && *str <= 'z') {
11             // 變為大寫字母。小寫和大寫字母的ASCII值有個固定的差值
12             *str -= 'a' - 'A';
13         }
14         
15         // 遍歷下一個字符
16         str++;
17     }
18     
19     // 返回字符串
20     return dest;
21 }

里面的代碼我就不詳細解釋了,重點看第2行的定義形式。

調用這個函數也非常簡單:

int main()
{
    // 定義一個字符串變量
    char str[] = "lmj";
    
    // 調用函數
    char *dest = upper(str);
    
    printf("%s", dest);
    return 0;
}

輸出結果:

 

二、指向函數的指針

看到這個標題,你可能覺得很詫異,指針竟然可以指向一個函數,那我就先解釋一下為什么指針可以指向一個函數

1.為什么指針可以指向一個函數

函數作為一段程序,在內存中也要占據部分存儲空間,它也有一個起始地址,即函數的入口地址。函數有自己的地址,那就好辦了,我們的指針變量就是用來存儲地址的。因此,可以利用一個指針指向一個函數。其中,函數名就代表着函數的地址

 

2.指向函數的指針的定義

定義的一般形式:函數的返回值類型 (*指針變量名)(形式參數1, 形式參數2, ...);

注意:形式參數的變量名可以省略,甚至整個形式參數列表都可以省略

 1 #include <stdio.h>
 2 
 3 int sum(int a, int b) {
 4     return a + b;
 5 }
 6 
 7 int main()
 8 {
 9     // 定義一個指針變量p,指向sum函數
10     int (*p)(int a, int b) = sum;
11     // 或者 int (*p)(int, int) = sum;
12     // 或者 int (*p)() = sum;
13     
14     // 利用指針變量p調用函數
15     int result = (*p)(1, 3);
16     // 或者 int result = p(1, 3);
17     
18     printf("%d", result);
19     return 0;
20 }

*先在第3行定義了一個sum函數,接收2個int類型的參數,返回值類型為int

* 然后在第10行定義了一個指向sum函數的指針變量p。注意p的定義形式:int (*p)(int a, int b),第1個int代表sum函數的返回值是int類型,然后*p是用括號()包住的,后面的int a和int b代表着sum函數的形參,其實完全可以省略。第10行、11行、12行都是可行

* 在第15行,先利用*p取出指向的函數,再傳入參數調用函數。也可以采用第16行中的做法,這樣就跟調用普通函數沒什么區別

最后的輸出結果:,毫無意外

 

3.使用注意

1> 由於這類指針變量存儲的是一個函數的入口地址,所以對它們作加減運算(比如p++)是無意義的。難道p++就會指向下一個函數了?可笑至極!!沒這回事。

2> 返回指針的函數的定char *upper(char *str) 和 指向函數的指針的定義int (*p)(int a, int b)非常相似,使用時特別注意區分

3> 指向函數的指針變量主要有兩個用途:

  • 調用函數

  • 將函數作為參數在函數間傳遞。我這么一說,可能還不是很明白,舉個例子。

 1 #include <stdio.h>
 2 
 3 // 減法運算
 4 int minus(int a, int b) {
 5     return a - b;
 6 }
 7 
 8 // 加法運算
 9 int sum(int a, int b) {
10     return a + b;
11 }
12 
13 // 這個counting函數是用來做a和b之間的計算,至於做加法還是減法運算,由函數的第1個參數決定
14 void counting( int (*p)(int, int) , int a, int b) {
15     int result = p(a, b);
16     printf("計算結果為:%d\n", result);
17 }
18 
19 int main()
20 {
21     // 進行加法運算
22     counting(sum, 6, 4);
23     
24     // 進行減法運算
25     counting(minus, 6, 4);
26     
27     return 0;
28 }

如果以后想再增加一種乘法運算,非常簡單,根本不用修改counting函數的代碼,只需要再增加一個乘法運算的函數

int mul(int a, int b) {
    return a * b;
}

后counting(mul, 6, 4);就可以進行乘法運算了

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM