【正文】
o m p u t e r \0 name[0] name[1] name[2] name[3] void print(char *name[ ],int n) { int i。 for(i=0。in。i++) printf(“%s\n”,name[i])。 } 指向指針數(shù)據(jù)的指針 ?在了解了指針數(shù)組的基礎(chǔ)上,需要了解指向指針數(shù)據(jù)的指針變量,簡稱為指向指針的指針。 F o l l o w \0 G r e a t \0 F O R T R A N \0 C o m p u t e r \0 name[0] name[1] name[2] name[3] name p 例 使用指向指針數(shù)據(jù)的指針變量。 char *name[]={“Follow”,“Great”, “FORTRAN”,“Computer”}。 char **p。 int i。 for(i=0。i5。i++) { p=name+i。 printf(%s\n,*p)。 } F o l l o w \0 G r e a t \0 F O R T R A N \0 C o m p u t e r \0 name[0] name[1] name[2] name[3] name p 例 有一個指針數(shù)組,其元素分別指向一個整型數(shù)組的元素,用指向指針數(shù)據(jù)的指針變量,輸出整型數(shù)組各元素的值。 include int main() {int a[5]={1,3,5,7,9}。 int *num[5]={amp。a[0],amp。a[1],amp。a[2], amp。a[3],amp。a[4]}。 int **p,i。 p=num。 for(i=0。i5。i++) { printf(%d ,**p)。 p++。 } printf(\n)。 return 0。 } amp。a[0] amp。a[1] amp。a[2] amp。a[3] amp。a[4] p 1 2 3 4 5 指針數(shù)組作 main函數(shù)的形參 ?指針數(shù)組的一個重要應(yīng)用是作為 main函數(shù)的形參。在以往的程序中, main函數(shù)的第一行一般寫成以下形式: int main() 或 int main(void) ?表示 main函數(shù)沒有參數(shù),調(diào)用 main函數(shù)時不必給出實參。 ?這是一般程序常采用的形式。 指針數(shù)組作 main函數(shù)的形參 ?實際上,在某些情況下, main函數(shù)可以有參數(shù),例如: int main(int argc,char *argv[]) 其中, argc和 argv就是 main函數(shù)的形參,它們是程序的“命令行參數(shù)”。 ?argv是 *char指針數(shù)組,數(shù)組中每一個元素 (其值為指針 )指向命令行中的一個字符串。 指針數(shù)組作 main函數(shù)的形參 ?通常 main函數(shù)和其他函數(shù)組成一個文件模塊,有一個文件名。 ?對這個文件進行編譯和連接,得到可執(zhí)行文件 ( 后綴為 .exe)。用戶執(zhí)行這個可執(zhí)行文件,操作系統(tǒng)就調(diào)用 main函數(shù),然后由 main函數(shù)調(diào)用其他函數(shù),從而完成程序的功能。 指針數(shù)組作 main函數(shù)的形參 ?main函數(shù)的形參是從 哪 里傳遞給它們的呢? ?顯然形參的值不可能在程序中得到。 ?main函數(shù)是操作系統(tǒng)調(diào)用的,實參只能由操作系統(tǒng)給出。 include int main(int argc,char *argv[]) { while(argc1) { ++argv。 printf(“%s\n”, *argv)。 argc。 } return 0。 } 在 VC++環(huán)境下 編譯、連接后,“工程” — “設(shè)置” — “調(diào)試” — “程序變量”中輸入“ China Beijing”,再運行就可得到結(jié)果 動態(tài)內(nèi)存分配與指向它的指針變量 什么是內(nèi)存的動態(tài)分配 怎樣建立內(nèi)存的動態(tài)分配 void指針類型 什么是內(nèi)存的動態(tài)分配 ?非靜態(tài)的局部變量是分配在內(nèi)存中的動態(tài)存儲區(qū)的,這個存儲區(qū)是一個稱為 棧 的區(qū)域 ?C語言還允許建立內(nèi)存動態(tài)分配區(qū)域,以存放一些臨時用的數(shù)據(jù),這些數(shù)據(jù)需要時隨時開辟,不需要時隨時釋放。這些數(shù)據(jù)是臨時存放在一個特別的自由存儲區(qū),稱為 堆 區(qū) 怎樣建立內(nèi)存的動態(tài)分配 ?對內(nèi)存的動態(tài)分配是通過系統(tǒng)提供的庫函數(shù)來實現(xiàn)的,主要有 malloc, calloc, free, realloc這 4個函數(shù)。 怎樣建立內(nèi)存的動態(tài)分配 1. malloc函數(shù) ?其函數(shù)原型為 void *malloc(unsigned int size)。 ?其作用是在內(nèi)存的動態(tài)存儲區(qū)中分配一個長度為 size的連續(xù)空間 ?函數(shù)的值是所分配區(qū)域的第一個字節(jié)的地址,或者說,此函數(shù)是一個指針型函數(shù),返回的指針指向該分配域的開頭位置 怎樣建立內(nèi)存的動態(tài)分配 malloc(100)。 ?開辟 100字節(jié)的臨時分配域,函數(shù)值為其第 1個字節(jié)的地址 ?注意指針的基類型為 void,即不指向任何類型的數(shù)據(jù),只提供一個地址 ?如果此函數(shù)未能成功地執(zhí)行(例如內(nèi)存空間不足),則返回空指針 (NULL) 怎樣建立內(nèi)存的動態(tài)分配 2. calloc函數(shù) ?其函數(shù)原型為 void *calloc(unsigned n,unsigned size)。 ?其作用是在內(nèi)存的動態(tài)存儲區(qū)中分配 n個長度為 size的連續(xù)空間,這個空間一般比較大,足以保存一個數(shù)組。 怎樣建立內(nèi)存的動態(tài)分配 ?用 calloc函數(shù)可以為一維數(shù)組開辟動態(tài)存儲空間, n為數(shù)組元素個數(shù),每個元素長度為size。這就是動態(tài)數(shù)組。函數(shù)返回指向所分配域的起始位置的指針;如果分配不成功,返回 NULL。如: p=calloc(50,4)。 開辟 50 4個字節(jié)的臨時分配域,把起始地址賦給指針變量 p 怎樣建立內(nèi)存的動態(tài)分配 3. free函數(shù) ?其函數(shù)原型為 void free(void *p)。 ?其作用是釋放指針變量p所指向的動態(tài)空間,使這部分空間能重新被其他變量使用。 p應(yīng)是最近一次調(diào)用 calloc或malloc函數(shù)時得到的函數(shù)返回值。 怎樣建立內(nèi)存的動態(tài)分配 free(p)。 ?釋放指針變量p所指向的已分配的動態(tài)空間 ?free函數(shù)無返回值 怎樣建立內(nèi)存的動態(tài)分配 4. realloc函數(shù) ?其函數(shù)原型為 void *realloc(void *p,unsigned int size)。 ?如果已經(jīng)通過 malloc函數(shù)或 calloc函數(shù)獲得了動態(tài)空間,想改變其大小,可以用recalloc函數(shù)重新分配。 怎樣建立內(nèi)存的動態(tài)分配 ?用 realloc函數(shù)將 p所指向的動態(tài)空間的大小改變?yōu)?size。 p的值不變。如果重分配不成功,返回 NULL。如 realloc(p,50)。 將 p所指向的已分配的動態(tài)空間改為 50字節(jié) 怎樣建立內(nèi)存的動態(tài)分配 ?以上 4個函數(shù)的聲明在 ,在用到這些函數(shù)時應(yīng)當(dāng)用“ include ”指令把 到程序文件中。 void指針類型 例 建立動態(tài)數(shù)組,輸入 5個學(xué)生的成績,另外用一個函放數(shù)檢查其中有無低于60分的,輸出不合格的成績。 void指針類型 ? 解題思路:用 malloc函數(shù)開辟一個動態(tài)自由區(qū)域,用來存 5個學(xué)生的成績,會得到這個動態(tài)域第一個字節(jié)的地址,它的基類型是 void型。用一個基類型為 int的指針變量 p來指向動態(tài)數(shù)組的各元素,并輸出它們的值。但必須先把 malloc函數(shù)返回的void指針轉(zhuǎn)換為整型指針,然后賦給 p1 include include int main() { void check(int *)。 int *p1,i。 p1=(int *)malloc(5*sizeof(int))。 for(i=0。i5。i++) scanf(%d,p1+i)。 check(p1)。 return 0。 } void check(int *p) { int i。 printf(They are fail:)。 for(i=0。i5。i++) if (p[i]60) printf(%d ,p[i])。 printf(\n)。 } 。指針就是地址,凡是出現(xiàn)“指針”的地方,都可以用“地址”代替,例如,變量的指針就是變量的地址,指針變量就是地址變量 ?要區(qū)別指針和指針變量。指針就是地址本身,而指針變量是用來存放地址的變量。 2. 什么叫“指向”?地址就意味著指向,因為通過地址能找到具有該地址的對象。對于指針變量來說,把誰的地址存放在指針變量中,就說此指針變量指向誰。但應(yīng)注意:只有與指針變量的基類型相同的數(shù)據(jù)的地址才能存放在相應(yīng)的指針變量中。 void *指針是一種特殊的指針,不指向任何類型的數(shù)據(jù),如果需要用此地址指向某類型的數(shù)據(jù),應(yīng)先對地址進行類型轉(zhuǎn)換。可以在程序中進行顯式的類型轉(zhuǎn)換,也可以由編譯系統(tǒng)自動進行隱式轉(zhuǎn)換。無論用哪種轉(zhuǎn)換,讀者必須了解要進行類型轉(zhuǎn)換 3. 要深入掌握在對數(shù)組的操作中怎樣正確地使用指針,搞清楚指針的指向。一維數(shù)組名代表數(shù)組首元素的地址 int *p,a[10]。 p=a。 ?p是指向 int類型的指針變量, p只能指向數(shù)組中的元素,而不是指向整個數(shù)組。在進行賦值時一定要先確定賦值號兩側(cè)的類型是否相同,是否允許賦值。 ?對“ p=a?!?,準(zhǔn)確地說應(yīng)該是: p指向 a數(shù)組的首元素 ,見 主教材中 表 。 (1)指針變量加(減)一個整數(shù) 例如: p++,p,p+i,pi,p+=i,p =i等均是指針變量加(減)一個整數(shù)。 ?將該指針變量的原值 (是一個地址 )和它指向的變量所占用的存儲單元的字節(jié)數(shù)相加(減)。 (2)指針變量賦值 ?將一個變量地址賦給一個指針變量 ?不應(yīng)把一個整數(shù)賦給指針變量 (3) 兩個指針變量可以相減 ?如果兩個指針變量都指向同一個數(shù)組中的元素,則兩個指針變量值之差是兩個指針之間的元素個數(shù) (4) 兩個指針變量比較 ?若兩個指針指向同一個數(shù)組的元素,則可以進行比較 ?指向前面的元素的指針變量“小于”指向后面元素的指針變量 ?如果 p1和 p2不指向同一數(shù)組則比較無意義 (5) 指針變量可以有空值,即該指針變量不指向任何變量,可以這樣表示: p=NULL。