前言
說(shuō)來(lái)慚愧, 本人做開(kāi)發(fā)時(shí)間也不算短了, 雖然空閑時(shí)間一直有做筆記, 但從來(lái)都沒(méi)寫(xiě)過(guò)技術(shù)博客澳厢。最近看了一些文章讓我意識(shí)到了記筆記和寫(xiě)博客的差距, 交流使人進(jìn)步, 禁閉使人落后! 決定不找任何借口, 突破自己, 并堅(jiān)持下去惦界。
因?yàn)橹坝浌P記的出發(fā)點(diǎn)是留著給自己進(jìn)行知識(shí)梳理的, 沒(méi)想過(guò)要發(fā)布出來(lái), 有些內(nèi)容吸收了各種博客加以自己的理解, 可能無(wú)法完整的列出參考鏈接, 在這里先感謝大佬們的付出和包涵, 歡迎批評(píng)斧正。
先來(lái)一篇非常基礎(chǔ)但很關(guān)鍵的C指針。
1、指針的概念
C是一門古老而強(qiáng)大的語(yǔ)言, 之所以強(qiáng)大, 很大部分體現(xiàn)在其靈活的指針運(yùn)用上。因此, 說(shuō)指針是C語(yǔ)言的靈魂, 一點(diǎn)都不為過(guò)瓣履。
那么, 什么是指針? 先了解一下概念。
與int练俐、float袖迎、double等其他數(shù)據(jù)類型一樣, 指針也是一種數(shù)據(jù)類型, 但這種數(shù)據(jù)類型所聲明的變量---即指針變量, 是一種特殊的變量, 是專門用來(lái)存儲(chǔ)內(nèi)存地址的。
一個(gè)指針變量有兩個(gè)屬性: 地址值和指針類型腺晾。地址值用來(lái)標(biāo)識(shí)指針?biāo)赶虻淖兞康氖椎刂? 指針類型告訴編譯器, 應(yīng)該以什么數(shù)據(jù)類型對(duì)指定的內(nèi)存區(qū)域進(jìn)行訪問(wèn)燕锥。
2、指針的聲明
概念清楚了, 指針又是如何使用的呢?
就像其他變量或常量一樣, 在使用指針之前, 必須先對(duì)其進(jìn)行聲明悯蝉。
指針變量聲明的一般形式為:
type *varName;
type 是指針的基類型, 它必須是一個(gè)有效的 C 數(shù)據(jù)類型, 如 int归形、char等;
type * 就是這個(gè)指針變量的數(shù)據(jù)類型;
varName是指針變量的名稱。
聲明指針變量時(shí), 如果沒(méi)有確切的地址可以賦值, 為指針變量賦一個(gè) NULL 值是一個(gè)良好的編程習(xí)慣鼻由。如: int *p = NULL;
2.1 關(guān)于空指針 NULL
上面說(shuō)聲明指針變量時(shí), 如果暫時(shí)不能確定其指向,可以先賦值為NULL暇榴。關(guān)于NULL在這里做幾點(diǎn)擴(kuò)展:
NULL 是一個(gè)定義在標(biāo)準(zhǔn)庫(kù)中的值為零的指針常量。賦為 NULL 的指針被稱為空指針蕉世。
#define NULL ((void *)0) // NULL的宏定義
外層的括號(hào)是為了防止宏定義歧義; 里層的括號(hào)則是強(qiáng)制類型轉(zhuǎn)換, 把0轉(zhuǎn)換成void * 類型, 本來(lái)void * 型就是用來(lái)存放地址的, 那么這里的0自然就是地址0了蔼紧。
空指針是有指向的指針, 但它指向的地址是很小的地址, 約定俗成為地址0x0, 是程序的起始, 這個(gè)地址不保存數(shù)據(jù), 同時(shí)不允許程序訪問(wèn)。所以空指針不能操作該地址, 我們就理解為“指針指向了空, 無(wú)法操作了”狠轻。
2.2 關(guān)于無(wú)確定類型指針 void *
那么NULL宏定義里面的void 型指針又是什么呢? 這個(gè)從“字面”上看起來(lái)更像空指針啊!
然而void * 型指針并不是空指針,這個(gè)類型的指針指向了實(shí)實(shí)在在的存放數(shù)據(jù)的地址, 但是該地址存放的數(shù)據(jù)的數(shù)據(jù)類型我們暫時(shí)不知道, 可以理解為無(wú)確定類型指針奸例。void 類型可以通過(guò)類型轉(zhuǎn)換強(qiáng)制轉(zhuǎn)換為任何其它類型的指針。
我們通過(guò)動(dòng)態(tài)內(nèi)存分配的例子加以理解:
char *str = (char *)malloc(sizeof(char)*10); // 動(dòng)態(tài)內(nèi)存分配
void *malloc(size_t __size); // 函數(shù)庫(kù)中malloc函數(shù)的聲明
malloc的全稱是memory allocation, 中文叫動(dòng)態(tài)內(nèi)存分配, 用于申請(qǐng)一塊連續(xù)的指定大小的內(nèi)存塊區(qū)域, 它以void *類型返回分配的內(nèi)存地址, 然后通過(guò)強(qiáng)制轉(zhuǎn)換改變?yōu)槠渌愋偷闹羔槨?br> 需要特別注意的是:
- void *型指針變量不能進(jìn)行算數(shù)運(yùn)算, 因?yàn)榫幾g器不能識(shí)別void *類型的長(zhǎng)度;
- void *型指針變量也不能使用*進(jìn)行取值操作, 因?yàn)榫幾g器不知道要取出的數(shù)據(jù)具體是什么類型, 想取值必須轉(zhuǎn)換為其它類型向楼。
3查吊、指針的初始化/賦值
聲明了一個(gè)變量, 要給他初始化才有意義。 給指針變量初始化/賦值其實(shí)就是讓指針指向某個(gè)地址湖蜕。
int a = 10, c = 20; // 定義并初始化兩個(gè)整形變量
// 定義一個(gè)指針變量p, 并初始化其值為變量a的地址(指向a的地址)
// 注意, 這個(gè)指針變量的變量名是p, 而不是 *p;
// 指針的類型是int *, 指針?biāo)赶虻念愋褪莍nt;
// 這里注意: 指針的類型(即指針本身的類型)和指針?biāo)赶虻念愋褪莾蓚€(gè)概念逻卖。
int *p = &a;
printf("a==%d, *p==%d\n", a, *p); // 輸出: a==10, *p==10
// 允許修改指針變量p所指向的地址(給指針變量重新賦值)
p = &c;
printf("c==%d, *p==%d\n", c, *p); // 輸出: c==20, *p==20
// 允許修改指針變量指向的內(nèi)存地址的內(nèi)容
// 此時(shí)p所指向的地址是變量c所在的內(nèi)存地址, 修改此地址的內(nèi)容也就是給該地址所存儲(chǔ)的變量c重新賦值
*p = 30;
printf("c==%d, *p==%d\n", c, *p); // 輸出: c==30, *p==30
p = a; // Error: 指針變量只能存儲(chǔ)地址, 給指針賦值其他類型的數(shù)據(jù)顯然不對(duì)
*p = &a; // Error: *在操作時(shí)表示指向操作, 操作指針指向的那個(gè)地址的內(nèi)容; 也就是說(shuō), 若p是一個(gè)有效指針, *p即為p所指向的地址的值, 此處*p是int類型, 不能將地址賦值給int
給初學(xué)者一點(diǎn)解惑: 聲明定義變量時(shí)的 * 和后面操作變量時(shí)的 * 以及&如何理解?
- * 在聲明定義指針變量時(shí) : 是指針聲明符, 說(shuō)明定義的這個(gè)變量是指針。如int *p;
- * 在操作指針變量時(shí): 是取值符, 取出指針?biāo)赶虻刂返闹抵剀H? *p = 30;
- & 寫(xiě)在變量前面: 是取址符, 任何變量都是放在內(nèi)存中的, 取址符&就是獲得變量在內(nèi)存中地址箭阶。
3.1 指針的值
指針的值是指針變量本身所存儲(chǔ)的數(shù)值, 這個(gè)值將被編譯器當(dāng)作一個(gè)地址, 而不是一個(gè)一般的數(shù)值。
前面說(shuō), 給指針變量初始化/賦值其實(shí)就是讓指針指向某個(gè)地址戈鲁。那么指針被初始化/賦值之后, 這個(gè)指針的值就是一個(gè)地址, 我們稱為指針?biāo)赶虻膬?nèi)存地址。實(shí)際上, 一個(gè)有效指針的值只能是一個(gè)地址嘹叫。
在64位機(jī)器里, 所有類型的指針的值都是一個(gè)64位二進(jìn)制, 因?yàn)?4位機(jī)器里內(nèi)存地址全都是64位婆殿。
4、指針和地址
既然指針的值就是地址, 那直接用地址就行了唄, 要什么指針, 搞得這么麻煩?
看過(guò)很多文章把他們混為一談, 認(rèn)為指針就是地址罩扇。其中有這樣的說(shuō)法: 變量的地址稱為變量的指針婆芦。存放指針的變量, 稱為指針變量怕磨。
我認(rèn)為這種說(shuō)法, 很容易讓初學(xué)者混淆概念, 讓人越看越糊涂。我的理解是:
變量的地址就是內(nèi)存地址, 是系統(tǒng)給每個(gè)存儲(chǔ)單元擬定的編號(hào);
存放地址的變量, 稱為指針變量消约。
4.1 地址是什么?
內(nèi)存中, 以8位二進(jìn)制(1個(gè)字節(jié))作為1個(gè)存儲(chǔ)單元, 每個(gè)存儲(chǔ)單元都有一個(gè)地址, 是一個(gè)整數(shù)編號(hào), 一般用十六進(jìn)制數(shù)表示肠鲫。
比如在IDE控制臺(tái)打印某個(gè)變量的地址, 會(huì)輸出類似0x7fff5fbff6ac這樣的十六進(jìn)制數(shù), 這個(gè)十六進(jìn)制數(shù), 就是這個(gè)變量在內(nèi)存中的地址, 如果這個(gè)變量占有多個(gè)字節(jié), 那么這個(gè)編號(hào)就是該變量的首地址(連續(xù)內(nèi)存中最前面的存儲(chǔ)單元的編號(hào))
我們通過(guò)這個(gè)地址, 就能找到內(nèi)存中對(duì)應(yīng)的存儲(chǔ)單元。找到了存儲(chǔ)單元, 也就能訪問(wèn)到內(nèi)存中所存儲(chǔ)的數(shù)據(jù)或粮。
一個(gè)存儲(chǔ)單元對(duì)應(yīng)一個(gè)字節(jié), 每個(gè)字節(jié)有8個(gè)二進(jìn)制位, 即能表示的最大的數(shù)是11111111(十進(jìn)制的255), 轉(zhuǎn)換為十六進(jìn)制是0xFF导饲。
反過(guò)來(lái)講, 一個(gè)存儲(chǔ)單元最多能存儲(chǔ)8位二進(jìn)制數(shù)(2位十六進(jìn)制數(shù))。
一點(diǎn)擴(kuò)展: 機(jī)器語(yǔ)言指令中出現(xiàn)的內(nèi)存地址, 都是邏輯地址, 需要轉(zhuǎn)換成線性地址, 再經(jīng)過(guò)MMU(CPU中的內(nèi)存管理單元)轉(zhuǎn)換成物理地址才能夠被訪問(wèn)到氯材。
4.2 指針和地址的關(guān)系
指針是由地址值和指針類型兩部分構(gòu)成的, 指向數(shù)據(jù)的指針不僅記錄該數(shù)據(jù)的在內(nèi)存中的存放的地址, 還記錄該數(shù)據(jù)的類型, 即在內(nèi)存中占用幾個(gè)字節(jié), 這是地址所不具有的渣锦。
正因?yàn)榈刂肥菦](méi)有類型的, 所以不能對(duì)地址進(jìn)行算術(shù)操作。
這些可以從5.2中的例子得到佐證氢哮。
5袋毙、指針的算術(shù)運(yùn)算(指針移動(dòng))
4.2講到, 地址不能進(jìn)行算數(shù)運(yùn)算, 而指針可以。
指針可以進(jìn)行四種算數(shù)運(yùn)算: ++冗尤、--听盖、+、-, 不過(guò)要注意的是必須是整數(shù)才行裂七。
這種運(yùn)算的意義和通常的數(shù)值的加減運(yùn)算是不一樣的, 指針的算數(shù)運(yùn)算以其所指向的類型所占字節(jié)長(zhǎng)度為單位, 也就是sizeof(指針?biāo)赶虻念愋?媳溺。
算數(shù)運(yùn)算之后指針的類型不變, 指針?biāo)赶虻念愋鸵膊蛔儭<覰, 就會(huì)向高地址移動(dòng); 減N, 則向低地址移動(dòng), 長(zhǎng)度是 N*sizeof(指針?biāo)赶虻念愋?碍讯。
舉個(gè)栗子:
int a = 10, c = 20;
printf("%p, %p, %p\n", &a, &c, &c+1); // 輸出: 0x7fff5fbff6ec, 0x7fff5fbff6e8, 0x7fff5fbff6ec
&c = &a; // 是非法的
先說(shuō)說(shuō) &a 是一個(gè)指針還是一個(gè)地址呢?
我的理解: 它是一個(gè)指針常量悬蔽。 原因如下:
1) IDE中可以看到&a 是有類型的, 其類型是int *。而地址沒(méi)有類型捉兴。
2) &a可以進(jìn)行算數(shù)運(yùn)算, 地址不能進(jìn)行算數(shù)運(yùn)算蝎困。
3) 給&a賦值是非法的, 也就是說(shuō)不能改變&a的指向, 所以它是一個(gè)常量。
關(guān)于這個(gè)問(wèn)題, 目前沒(méi)有找到權(quán)威的說(shuō)法, 暫且認(rèn)為&a是指針常量, 基本可以解釋的通, 如有不同見(jiàn)解, 歡迎討論倍啥。
從print輸出可以看到, &a與&c+1相等, 都比&c大4, 而sizeof(int)==4;
也就是說(shuō), a的地址比c的地址高了4個(gè)字節(jié), 那為什么a比c的地址高呢?
因?yàn)闂禾乘?臻g是從高地址往低地址擴(kuò)展的, 先聲明的a, 那a的地址自然比c的地址高, 高出的大小剛好是變量c所占內(nèi)存空間的大小。如此, &c+1得到的也就是變量a的地址虽缕。
5.1 指針變量之間的算數(shù)運(yùn)算:
兩個(gè)同一類型的指針變量是可以相減的, 他們的意義表示兩個(gè)指針指向的內(nèi)存位置之間相隔多少個(gè)元素(注意是元素, 并不是字節(jié)數(shù)), 一般應(yīng)用在數(shù)組元素之間始藕。
兩個(gè)指針不能進(jìn)行加法運(yùn)算, 這是非法操作, 因?yàn)檫M(jìn)行加法后, 得到的結(jié)果指向一個(gè)不知所向的地方, 而且毫無(wú)意義。
5.2 指針變量之間的比較
指針可以用關(guān)系運(yùn)算符進(jìn)行比較, 如 ==氮趋、< 和 >伍派。其本質(zhì)也就是指針變量之間的相減運(yùn)算。
6剩胁、指針的類型 和 指針?biāo)赶虻念愋?
上面提到了一個(gè)注意點(diǎn): 指針的類型和指針?biāo)赶虻念愋褪莾蓚€(gè)概念诉植。這點(diǎn)很關(guān)鍵, 不可混淆。
6.1 先說(shuō)說(shuō)什么是指針的類型?
任何變量都有自己的數(shù)據(jù)類型, 指針變量也有其數(shù)據(jù)類型, 指針的類型是指針變量本身所具有的數(shù)據(jù)類型昵观。
就如同 int a = 10; 那么變量a的數(shù)據(jù)類型就是int晾腔∩嘞。可以大致理解為: 用什么聲明這個(gè)變量, 那么這個(gè)變量的類型就是什么。從語(yǔ)法上看, 把指針聲明語(yǔ)句里的指針變量名去掉, 剩下的部分就是這個(gè)指針的類型灼擂。
下面列舉幾個(gè)例子:
1) int *ptr; // 指針的類型是int* (用 int *聲明的變量ptr)
2) char *ptr; // 指針的類型是char*
3) int **ptr; // 指針的類型是int** (用 int **聲明的變量ptr)
4) int(*ptr)[3]; // 指針的類型是int(*)[3]
5) int *(*ptr)[4]; // 指針的類型是int *(*)[4]
6.2 什么是指針指向的類型?
我們常說(shuō), 指針變量p指向變量xx的地址, 那么變量xx的數(shù)據(jù)類型, 就是指針變量p所指向的類型壁查。指針?biāo)赶虻念愋蜎Q定了編譯器將把那塊內(nèi)存區(qū)里的數(shù)據(jù)當(dāng)做什么來(lái)看待。
從語(yǔ)法上看, 把指針聲明語(yǔ)句中的指針名及其左邊的第一個(gè)指針聲明符*去掉, 剩下的就是指針?biāo)赶虻念愋汀?br>
還是用上面的例子:
1) int *ptr; // 指針?biāo)赶虻念愋褪莍nt
2) char *ptr; // 指針?biāo)赶虻牡念愋褪莄har
3) int **ptr; // 指針?biāo)赶虻牡念愋褪莍nt *
4) int (*ptr)[3]; // 指針?biāo)赶虻牡念愋褪莍nt()[3]
5) int *(*ptr)[4]; // 指針?biāo)赶虻牡念愋褪莍nt*()[4]
7剔应、指針與數(shù)組
指針可以存放int類型變量的地址, 指向int類型的變量; 同理, 指針也可以指向數(shù)組睡腿。
舉個(gè)栗子:
int arr[] = {0, 1, 2, 3, 4, 5};
int *p;
p = arr;
數(shù)組名arr是指向 &arr[0] 的指針, 即指向數(shù)組首元素的地址。
但是arr并不是指針變量, 而是一個(gè)指針常量, 它的類型是int [6]领斥。
即arr這個(gè)指針是個(gè)常量, arr指向的數(shù)值(arr[0])可以改變, 而arr所保存的地址不能改變嫉到。
也就是說(shuō) arr[0] = 6;是完全合法的, 而給arr賦值, 如: arr = p; 就不合法。
p是個(gè)指針變量, 指向了arr的值, 也就是數(shù)組arr的首元素的地址月洛。
p和arr都具有指針值, 都可以進(jìn)行間接訪問(wèn)和下標(biāo)引用操作:
printf("%d--%d--%d--%d\n", *(arr+1), arr[1], *(p+1), p[1]); // 輸出: 1--1--1–1
但p是變量, 我們可以使用p++來(lái)遍歷數(shù)組元素, 這就是p和arr最大的不同:
for (int i=0; i<6; i++) printf("%d\n", *p++);
指針牽扯到數(shù)組, 還會(huì)引申出一系列的問(wèn)題, 如字符串何恶、二級(jí)指針、二維數(shù)組嚼黔、指針數(shù)組细层、數(shù)組指針等等, 這里限于篇幅, 暫不討論, 后面會(huì)單獨(dú)寫(xiě)一篇關(guān)于指針和數(shù)組的詳解。
8、指針與結(jié)構(gòu)體
就像數(shù)組指針一樣, 指向結(jié)構(gòu)體的指針存儲(chǔ)了結(jié)構(gòu)體第一個(gè)元素的內(nèi)存地址。結(jié)構(gòu)體的指針必須聲明和結(jié)構(gòu)體類型保持一致, 或者聲明為void類型尸曼。
8.1 如何定義指向結(jié)構(gòu)體變量的指針?
- 拷貝結(jié)構(gòu)體類型 和 結(jié)構(gòu)體變量名稱
- 在類型和名稱中間加上*
當(dāng)指針指向結(jié)構(gòu)體之后如何利用指針訪問(wèn)結(jié)構(gòu)體的成員變量? - 結(jié)構(gòu)體變量名稱.屬性;
- (*結(jié)構(gòu)體指針變量名稱).屬性;
- 使用指向運(yùn)算符->, 結(jié)構(gòu)體指針變量名稱->屬性;
舉例說(shuō)明:
struct Person {
int age;
char *name;
double height;
}; // 定義結(jié)構(gòu)體類型Person
struct Person sp = {26, "xiaoming", 1.80}; // 定義結(jié)構(gòu)體變量sp
struct Person *sip = &sp; // 定義指向結(jié)構(gòu)體的指針sip, *sip === sp
sp.name = "xiaohong";
(*sip).name = "xiaomei"; // 運(yùn)算符.的優(yōu)先級(jí)比*高, 加上()先取值再查找
sip->name = "laowang";
關(guān)于結(jié)構(gòu)體這里也暫不做過(guò)多討論搓译。
9霉祸、指針與函數(shù)
9.1 函數(shù)指針
函數(shù)也會(huì)占用一塊存儲(chǔ)空間, 所以函數(shù)也有自己的地址, 那么指向這塊地址的指針變量就是函數(shù)指針。
函數(shù)指針有兩個(gè)用途: 調(diào)用函數(shù)、做函數(shù)的參數(shù)(回調(diào)函數(shù))。
9.1.1 函數(shù)指針的聲明方式:
返回值類型 (* 指針變量名) (形參列表);
注: “返回值類型”說(shuō)明函數(shù)的返回類型胎撇,“(指針變量名 )”中的括號(hào)不能省,括號(hào)改變了運(yùn)算符的優(yōu)先級(jí)殖氏。
// 方法1 直接聲明
void (*p_func)(int, int, float) = NULL;
// 方法2 利用typedef取別名, 再聲明
typedef void (*tp_func)(int, int, float);
tp_func p_func = NULL;
9.1.2 利用函數(shù)指針調(diào)用函數(shù)
利用函數(shù)指針調(diào)用函數(shù)實(shí)例:
int max(int x, int y) {
return x > y ? x : y;
}
int main(void) {
// 定義函數(shù)指針p指向函數(shù)max的地址
int (* p)(int, int) = & max; // &可以省略, 函數(shù)名就是地址, 可以將它賦值給指向函數(shù)的指針
int a, b, c, d;
printf("請(qǐng)輸入三個(gè)數(shù)字:");
scanf("%d %d %d", & a, & b, & c);
d = p(p(a, b), c); // 與直接調(diào)用函數(shù)等價(jià), d = max(max(a, b), c)
printf("最大的數(shù)字是: %d\n", d);
return 0;
}
編譯執(zhí)行, 輸出結(jié)果如下: 請(qǐng)輸入三個(gè)數(shù)字, 假設(shè)輸入了1 2 3
則打印輸出, 最大的數(shù)字是: 3
9.1.3 函數(shù)指針與回調(diào)函數(shù)
回調(diào)函數(shù)就是一個(gè)通過(guò)函數(shù)指針調(diào)用的函數(shù)晚树。如果你把函數(shù)的指針作為參數(shù)傳遞給另一個(gè)函數(shù), 當(dāng)這個(gè)指針被用來(lái)調(diào)用其所指向的函數(shù)時(shí), 我們就說(shuō)這是回調(diào)函數(shù)。
回調(diào)函數(shù)不是由該函數(shù)的實(shí)現(xiàn)方直接調(diào)用, 而是在特定的事件或條件發(fā)生時(shí)由另外的一方調(diào)用的, 用于對(duì)該事件或條件進(jìn)行響應(yīng)雅采。
因?yàn)榭梢园颜{(diào)用者與被調(diào)用者分開(kāi), 所以調(diào)用者不關(guān)心誰(shuí)是被調(diào)用者爵憎。它只需知道存在一個(gè)具有特定原型和限制條件的被調(diào)用函數(shù)。簡(jiǎn)而言之, 回調(diào)函數(shù)就是允許用戶把需要調(diào)用的方法的指針作為參數(shù)傳遞給一個(gè)函數(shù), 以便該函數(shù)在處理相似事件的時(shí)候可以靈活的使用不同的方法婚瓜。
回調(diào)函數(shù)實(shí)例:
// 函數(shù)A, 形參需要傳入 int型數(shù)組, 數(shù)組大小, 函數(shù)指針
void populate_array(int *array, size_t arraySize, int (*getNextValue)(void)) {
for (size_t i=0; i<arraySize; i++)
array[i] = getNextValue();
}
// 函數(shù)B, 函數(shù)指針?biāo)赶虻暮瘮?shù)
int getNextRandomValue(void) {
return rand(); // 獲取隨機(jī)值
}
int main(void) {
int myarray[10];
// 使用函數(shù)指針回調(diào)
populate_array(myarray, 10, getNextRandomValue);
for(int i = 0; i < 10; i++) {
printf("%d", myarray[i]);
}
printf("\n");
return 0;
}
9.2 指針函數(shù)
還有一個(gè)概念叫做指針函數(shù): 即返回值是指針類型的函數(shù), 這篇主要說(shuō)指針, 也不多贅述
指針函數(shù)的定義格式:
類型名 *函數(shù)名(函數(shù)參數(shù)列表);
實(shí)例:
int *pfun(int, int);
暫時(shí)先寫(xiě)這些, 以后再補(bǔ)充宝鼓。
ps: 第一次寫(xiě)簡(jiǎn)書(shū), 有點(diǎn)緊張??, 排版都排不好, 大神勿噴。