C語言程序設(shè)計教程課件:指針_第1頁
C語言程序設(shè)計教程課件:指針_第2頁
C語言程序設(shè)計教程課件:指針_第3頁
C語言程序設(shè)計教程課件:指針_第4頁
C語言程序設(shè)計教程課件:指針_第5頁
已閱讀5頁,還剩85頁未讀 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

指針6.1指針與指針變量6.2指針與數(shù)組6.3指針與函數(shù)本章小結(jié)

本章要點

指針是C語言的重要數(shù)據(jù)類型,在C語言中占有重要的地位,是C語言的精髓,也是比較難掌握的內(nèi)容。C語言的高度靈活性及其超強(qiáng)的表達(dá)能力,在很大程度上源于巧妙而恰當(dāng)?shù)厥褂弥羔槨l`活、正確地使用指針,能夠有效、方便地處理數(shù)組和字符串,在函數(shù)之間傳送數(shù)據(jù),有效地表示和處理復(fù)雜的數(shù)據(jù)類型,特別有利于動態(tài)數(shù)據(jù)的管理。指針可以直接處理內(nèi)存地址,因此可以使編寫的程序簡潔、緊湊和高效。

6.1指針與指針變量

6.1.1指針的概念1.內(nèi)存及其地址我們知道,盡管計算機(jī)技術(shù)發(fā)展日新月異,但現(xiàn)代計算機(jī)仍然采用“基于存儲程序和程序控制”的馮·諾依曼原理。“存儲程序”就是在程序運(yùn)行之前將程序和數(shù)據(jù)存入計算機(jī)內(nèi)存中,而內(nèi)存是以字節(jié)為單位的連續(xù)存儲空間。為了方便地尋找內(nèi)存中存放的程序?qū)嶓w(變量、數(shù)組、函數(shù)等),每個內(nèi)存單元都有一個編號,稱為內(nèi)存地址(簡稱地址)。

C語言規(guī)定,編程時必須首先說明變量名、數(shù)組名。編譯時,系統(tǒng)會根據(jù)程序中定義的數(shù)據(jù)類型給變量或數(shù)組分配相應(yīng)大小的內(nèi)存空間(即多少個內(nèi)存單元)。例如:

charc;

nti;

floatf;

c是字符型變量,在內(nèi)存中占1個字節(jié)(即占1個存儲單元),地址為2010;i是整型變量,在內(nèi)存中占4個字節(jié),分別是2011~2014,地址為2011;f是單精度變量,在內(nèi)存中占4個字節(jié),分別是2015~2018,地址是2015,如圖6-1所示。圖6-1變量c、i和f的地址

2.指針與指針變量

(1)指針:某個程序?qū)嶓w(如變量、數(shù)組或函數(shù)等)所占用的存儲單元的首地址。例如在圖6-2中,地址2011是變量i的指針。由于地址唯一確定程序?qū)嶓w的存儲位置,就像路標(biāo)一樣,故形象地稱為指針。圖6-2指針和指針變量

(2)指針變量:專門存放變量(或其他程序?qū)嶓w)地址的變量。

例如,可以通過語句iPointer=&i;將變量i的地址(2011)存放到iPointer中,iPointer就是指針變量,如圖6-2所示。這樣,由變量iPointer的值(地址,圖6-2中為2011)就可以找到變量i,稱變量iPointer指向變量i,它存放的地址就稱為“指針”。因此,指針就是地址。

指針變量也需要存儲單元(存放地址值的整數(shù)),它本身也有地址。

3.變量地址的獲取

由于變量的存儲單元是在編譯時(對靜態(tài)存儲變量)或程序運(yùn)行時(對動態(tài)存儲變量)分配的,因此變量的地址不能人為確定,而要通過取地址運(yùn)算符&獲取。例如,在如下的程序段中:

charc;

inti;

floatf;

scanf("%d%f%c",&i,&f,&c);

由&i、&f和&c分別得到變量i、f和c的內(nèi)存地址。值得注意的是,由于常量和表達(dá)式?jīng)]有用戶可操作的內(nèi)存地址,因此&不能作用在常量或表達(dá)式上。

4.直接訪問與間接訪問

(1)直接訪問:按變量名或其地址存取變量值。例如:

inti;

scanf("%d",&i);

printf("%d\n",i);

(2)間接訪問:通過指針變量(如iPointer)訪問它指向的變量(如i)的方式叫間接訪問方式。即先找到存放“i的地址”的變量iPointer,從中取出i的地址(2011),然后到2011、2012、2013、2014四個存儲單元取出i的值。

6.1.2指針變量的定義與初始化

1.指針的類型

指針也是有類型的,指針的類型又稱指針的基類型。指針類型就是它所指向的程序?qū)嶓w(如變量、數(shù)組)的類型,由此可確定程序?qū)嶓w所占內(nèi)存的字節(jié)數(shù)。當(dāng)指針變量移動(存放的地址值變化)時,以這個字節(jié)數(shù)為單位,因此就用這個類型定義指針變量,且往往與它指向的程序?qū)嶓w一道定義,稱為“指針變量的類型”或簡稱“類型”。

2.指針變量的定義

對指針變量的定義包括三個內(nèi)容:

(1)指針類型說明,即定義變量為一個指針變量;

(2)指針變量名;

(3)變量值(指針)所指向變量的數(shù)據(jù)類型。

指針變量定義的形式為:

類型*指針變量名1,*指針變量名2,…;

其中,*表示這是一個指針變量,變量名即為定義的指針變量名,類型說明符表示本指針變量所指向變量的數(shù)據(jù)類型。定義了指針變量以后,就為指針變量分配存儲單元,準(zhǔn)備存儲地址值。例如:

int*p1;

表示p1是一個指針變量,它的值是某個整型變量的地址。或者說p1指向一個整型變量,至于p1究竟指向哪一個整型變量,應(yīng)由向p1賦予的地址來決定。

說明:

(1)“*”表示其后的變量是指針變量,而不是指針變量名的一部分,即指針變量名是p1、p2、p3,不是*p1、*p2、*p3。

(2)一個指針變量只能指向同類型的變量,如p2只能指向浮點變量,不能時而指向一個浮點變量,時而又指向一個整型或字符型變量。

(3)指針變量中只能存放地址,不能將一個非地址類型的數(shù)據(jù)(如常數(shù))賦給一個指針變量,但0(NULL)除外。例如:

p1=100; /*錯誤*/

p1=NULL; /*正確,表示它不指向任何對象,即空指針*/

(4)指針變量定義后,如果沒有初始化,則變量值是不確定的,使用前必須先賦值。

3.指針變量的初始化

上面定義的指針變量都沒有存儲地址值,也就沒有指向,其值是隨機(jī)的。指針變量同普通變量一樣,使用之前不僅要定義說明,而且必須賦予具體的值。未經(jīng)賦值的指針變量不能使用,否則將造成系統(tǒng)混亂,甚至死機(jī)。只有被賦值以后,指針變量才有確定的指向。

給指針變量賦地址值的方法有:

(1)在程序執(zhí)行部分賦值。

(2)定義指針變量時初始化賦值。定義指針變量時初始化賦值的形式為:

類型*指針變量名=&變量名,…;

例如:inta;

int*p=&a;

或者:inta,*p=&a;

6.1.3指針變量的使用

C語言中提供了兩個與指針有關(guān)的運(yùn)算符:

(1)?&:取地址運(yùn)算符,作用是獲得變量所占用的存儲單元的首地址(即該變量的地址)。例如:

inta=10,*p;

p=&a; /*&a表示變量a的地址*/

(2)??*:指針運(yùn)算符(或稱“間接訪問運(yùn)算符”),作用是通過指針變量來訪問它所指向變量的值(取數(shù)據(jù)或存數(shù)據(jù))。例如:

printf("%d\n",*p); /*輸出指針變量p所指向變量a的值,*p與a等價,即10*/

說明:

★在定義指針變量時,“*”表示其后的變量是指針變量;在執(zhí)行部分的表達(dá)式中,“*”是指針運(yùn)算符。

★&和*都為單目運(yùn)算符,優(yōu)先級高于所有雙目運(yùn)算符,與其他的單目運(yùn)算符具有相同的優(yōu)先級和結(jié)合性(右結(jié)合性)。

★&a不能出現(xiàn)在賦值號的左邊。

★運(yùn)算符&只能作用于變量和數(shù)組元素,不能作用于表達(dá)式或常量。

★根據(jù)*運(yùn)算符的作用,*運(yùn)算符和取地址運(yùn)算符&互逆,即:

*(&a)==a&(*p)==p

★?p、&a與&*p完全等價,即下面3個語句等價:

scanf("%d",p);

scanf("%d",&a);

scanf("%d",&*p);

?★a、*p與*&a完全等價,即下面3個語句等價:

printf("%d",a)

;

printf("%d",*p)

;

printf("%d",*&a)

;

★C語言中,*運(yùn)算符表示兩種運(yùn)算,編譯系統(tǒng)能夠自動根據(jù)上下文環(huán)境來區(qū)別*的作用。

inta=2,b,c;

int*p=&b

; /*指針變量p指向b*/

*p=3; /*表示指針運(yùn)算符*/

c=a**p /*第1個*表示乘法運(yùn)算符,第2個*表示指針運(yùn)算符*/

★指針變量可出現(xiàn)在表達(dá)式中,例如:

inta,b,*p=&a; /*指針變量p指向a,則*p可出現(xiàn)在a能出現(xiàn)的任何地方*/

b=*p+1; /*把a(bǔ)的內(nèi)容與1相加后賦給b*/

b=++*p; /*相當(dāng)于++(*p),即把p

指向的存儲單元內(nèi)容加1后再賦給b*/

b=*p++; /*相當(dāng)于b=*p;p++;*/

6.1.4指針的基本運(yùn)算

指針是一個地址的概念,指針的值是某種類型變量的地址,可以用指針間接訪問某些變量,參與數(shù)值運(yùn)算。然而指針本身也可以參與運(yùn)算,它可以參與賦值運(yùn)算、部分算術(shù)運(yùn)算和關(guān)系運(yùn)算。

1.指針變量的賦值運(yùn)算

如果指針變量沒有一個確定的指向而進(jìn)行*運(yùn)算,在編譯時會出現(xiàn)警告性錯誤。為指針變量賦值,使其有明確的指向,是使用指針變量的前提。而C語言中,變量的地址是編譯系統(tǒng)分配的,對用戶完全透明,用戶不知道變量的具體地址。

因此,對指針賦值的常見方式有:

(1)把符號常量NULL賦給指針變量。

例如:int*p=NULL;

說明:NULL由stdio.h定義為0,它也等同于'\0',意為“空指針”。如果一個指針的值為NULL,表示它不指向任何對象。

(2)把一個變量的地址賦給指針。

例如:語句inta,*p=&a;

說明:該語句執(zhí)行后,p指向a。不要把一個變量的地址賦給與該變量類型不同的指針變量,否則會出現(xiàn)警告性錯誤。

(3)把一個指針的值賦給同類型的另一個指針。

例如:inta,*p=&a,*q;q=p;

說明:可以在相同類型的指針之間進(jìn)行賦值,結(jié)果是兩個指針指向同一個對象。

【例6-1】編一程序,交換兩個變量的值。

執(zhí)行過程如圖6-3、圖6-4、圖6-5、圖6-6所示。

2.指針的算術(shù)運(yùn)算

指針的值是某種類型變量地址所允許的整數(shù),但指針不是整數(shù),不能將任意整數(shù)賦給指針變量。因為指針的值是某特定類型變量的地址,而變量地址是由編譯系統(tǒng)分配的,所以指針運(yùn)算不能像整型變量那樣,對指針進(jìn)行所有的算術(shù)運(yùn)算。

除了賦值運(yùn)算外,有意義的指針運(yùn)算包括下面要介紹的算術(shù)運(yùn)算和關(guān)系運(yùn)算。但前提是:參加運(yùn)算的指針代表了一些連續(xù)的存儲單元。前面章節(jié)介紹了,只有數(shù)組元素才占據(jù)內(nèi)存一些連續(xù)的存儲單元,而每個數(shù)組元素相當(dāng)于一個普通變量。所以,下面介紹的指針運(yùn)算,原則上只適用于數(shù)組和字符串兩種情況。

指針可進(jìn)行的算術(shù)運(yùn)算有:

(1)指針加、減整數(shù)運(yùn)算。

假定有定義:

intn;float*p;

表達(dá)式p±n(其中n≥0)指向的是p所指的數(shù)據(jù)存儲單元之后(或之前)的第n個數(shù)據(jù)存儲單元。注意,這里的數(shù)據(jù)存儲單元不是內(nèi)存單元,內(nèi)存單元的大小是固定的(一般按1字節(jié)計算),而數(shù)據(jù)存儲單元的大小與數(shù)據(jù)類型有關(guān)。

在VC中,整型數(shù)據(jù)占4個字節(jié),p是指向整型數(shù)組元素的指針,假設(shè)p的值是2010,則p+1=2014,p+2=2018,…,p+n=2010+4*n,如圖6-7所示。圖6-7float數(shù)據(jù)存儲單元

(2)指針變量的++和--運(yùn)算。

注意:對指針進(jìn)行++或--運(yùn)算,指針的值變成后一個或前一個變量(或元素)的地址,并不表示指針的值加1或減1。

例如,若有語句:

inta[10],*p=&a[0];

并假設(shè)數(shù)組元素a[0]的地址為2010,當(dāng)執(zhí)行p++后,p指向數(shù)組元素a[1]。因為a數(shù)組的每個元素在內(nèi)存中占4個字節(jié),故a[1]的地址為:

2010+sizeof(int)=2014

所以執(zhí)行p++后,p的值為2014。

(3)指向同一數(shù)組不同元素的指針減法運(yùn)算。

兩個類型相同的指針可以相減,其結(jié)果是這兩個地址差之間能夠存放的數(shù)據(jù)個數(shù)(數(shù)據(jù)類型為指針?biāo)赶蜃兞康念愋?。

例如,若有定義:

int*p1,*p2;

假設(shè)p1指向2010,p2指向2018,則p2-p1的值為:(2018-2010)/sizeof(int)=2,如圖6-8所示。圖6-8指針減法運(yùn)算

3.指針的關(guān)系運(yùn)算

使用關(guān)系運(yùn)算符<、<=、>、>=、==、和!=可以比較指針值的大小。

指針的關(guān)系運(yùn)算即比較指針(地址)大小的運(yùn)算。如果p和q是指向相同類型的指針變量,并且p和q指向同一段連續(xù)的存儲空間,p的地址值小于q,則表達(dá)式p<q的值為1,否則該表達(dá)式的值為0。

6.2指?針?與?數(shù)?組

6.2.1指針與一維數(shù)組一個數(shù)組是由連續(xù)的一塊內(nèi)存單元組成的。數(shù)組的地址是指數(shù)組的首地址,即編譯時給數(shù)組分配的一段存儲空間的起始地址。一個數(shù)組也是由各個數(shù)組元素(下標(biāo)變量)組成的,每個數(shù)組元素按其類型不同占有幾個連續(xù)的內(nèi)存單元。數(shù)組名代表數(shù)組起始地址,是一個常量。數(shù)組中每個數(shù)組元素也是占有一定存儲空間的,即每一個數(shù)組元素也有地址。

定義一個指向數(shù)組元素的指針變量的方法,與前面定義指針變量的方法相同,格式仍然為:

類型*指針變量名,……;

例如:

inta[10]; /*定義a為包含10個整型數(shù)據(jù)的數(shù)組*/

int*p; /*定義p為指向整型變量的指針*/

應(yīng)當(dāng)注意:因為數(shù)組為int型,所以指針變量也應(yīng)為指向int型的指針變量。下面是對指針變量賦值:

p=&a[0];

把a(bǔ)[0]元素的地址賦給指針變量p。也就是說,p指向a數(shù)組中下標(biāo)為0的元素。

獲得地址的方法為:

指針變量名=&數(shù)組元素;

或:

指針變量名?=?一維數(shù)組名;

當(dāng)一個指針指向數(shù)組后,對數(shù)組元素的引用,既可以使用下標(biāo)法,也可以使用指針法。并且,用指針訪問數(shù)組元素,程序的效率更高;相對來說,使用下標(biāo)訪問數(shù)組元素程序更清晰。

說明:

(1)數(shù)組名就是指針,是數(shù)組的首地址,它是地址常量,不能像指針變量那樣前后移動。下面的賦值是錯誤的:

a=a+1;

(2)指針變量可以存放數(shù)組的起始地址,也可以存放數(shù)組元素的地址。

(3)指向數(shù)組元素的指針變量,與指向普通變量的指針變量用法相同。

例如:

inta[10],*p;p=a; /*p存放數(shù)組a的首地址,等價于:p=&a[0];*/

根據(jù)前面介紹的指針?biāo)阈g(shù)運(yùn)算規(guī)則,p+1指向數(shù)組元素a[1],p+2指向數(shù)組元素a[2],p+i指向數(shù)組元素a[i]。對于inta[10],*p=a;?,則:

★p+i和a+i都是數(shù)組元素a[i]的地址,即&a[i]。

★*(p+i)和*(a+i)就是數(shù)組元素a[i]。

★指向數(shù)組的指針變量,也可將其看做是數(shù)組名,因而可按下標(biāo)法來使用。

例如,p[i]等價于a[i],也等價于*(p+i)。

★*p表示取得當(dāng)前所指元素之值。

★p++(或p+=1)表示p指向下一個元素,而不是簡單地使指針變量p的值+1。其地址值為:

★p(地址)+1*size(size為一個元素占用字節(jié)數(shù))

例如,設(shè)指針變量p的當(dāng)前值為2010,則p+1的值為2010+1*4=2014,而不是2011。

★*p++等價于*(p++),相當(dāng)于a[i++]。先按p的原值進(jìn)行*運(yùn)算,即*p,得到a[0]的值,然后使p的值改變p=p+1,指向下一個數(shù)組元素a[1]。

?

★*p--等價于*(p--),先*p,再p=p–1。

★*(++p)相當(dāng)于a[++i],表示p=p+1,再*p。

★*(--p)相當(dāng)于a[--i],表示p=p-1,再*p。

★(*p)++表示p所指向元素的值加1,即a[i]+1。

【例6-2】編寫程序,輸入5個整數(shù)存儲在數(shù)組中并輸出。

算法一:指針法。

算法二:指針法,通過數(shù)組名計算元素的地址,找出元素的值。

算法三:下標(biāo)法。

算法四:下標(biāo)法。

算法五:指針移動法,使指針變量p每次進(jìn)行自加運(yùn)算,指向下一個元素。

從上述5種算法可以看出:

(1)指針p指向a數(shù)組的首地址時,p+1、a+i都表示數(shù)組元素a[i]的地址,所以*(p+i)、*(a+i)都表示a[i]的內(nèi)容。

(2)可以將指向數(shù)組首地址的指針變量用數(shù)組方式操作,即a[i]和p[i]等價,此時下面4項是等價的:

a[i]p[i]*(p+i)*(a+i)

(3)上面前4個算法中,指針變量p保持不變;而算法5中p發(fā)生了變化,但不允許進(jìn)行a++操作,因為a作為數(shù)組名是地址常數(shù),其值是不能修改的。所以,下面算法是錯誤的:

6.2.2指針與二維數(shù)組

用指針變量可以指向一維數(shù)組,也可以指向二維數(shù)組。二維數(shù)組的首地址稱為二維數(shù)組的指針,存放這個指針的變量稱為指向二維數(shù)組的指針變量。二維數(shù)組的指針并不是一維數(shù)組指針的簡單拓展,它具有自己的獨特性質(zhì),在概念和使用上,指向二維數(shù)組的指針比指向一維數(shù)組的指針更復(fù)雜。

1.二維數(shù)組的地址

設(shè)有整型二維數(shù)組定義如下:

inta[2][3]={{1,2,3},{4,5,6}};

設(shè)數(shù)組a的首地址為2010,則各元素的地址及其值如圖6-9所示。

根據(jù)數(shù)組的定義,一個二維數(shù)組由若干個一維數(shù)組所組成,其中每一個一維數(shù)組包含若干個元素。因此,數(shù)組a可分解為2個一維數(shù)組,即a[0]、a[1]。每一個一維數(shù)組又含有3個元素,如圖6-10所示。a[0]數(shù)組含有a[0][0]、a[0][1]、a[0][1]共3個元素,a[1]數(shù)組含有a[1][0]、a[1][1]、a[1][2]共3個元素。圖6-9各元素的地址及其值圖6-10數(shù)組a分解為2個一維數(shù)組

從二維數(shù)組的角度看,數(shù)組a代表二維數(shù)組的首地址,也是第0行的首地址,等于2010。a+1代表第1行的首地址,從a[0]到a[1]要跨越一個一維數(shù)組的空間(包含3個整型元素,共12個字節(jié)),則a+1為2022。這種地址稱為行地址。

a[0]、a[1]既然是一維數(shù)組名,C語言規(guī)定:數(shù)組名代表數(shù)組首元素的地址,因此a[0]表示第0行中第0列元素的地址,即&a[0][0],值為2010;a[1]表示第1行第0列元素的地址,即&a[1][0],值為2022。a[0]+1表示第0行中第1列元素的地址&a[0][1];a[1]+2=&a[1][2]……這種地址稱為列地址。

雖然a和a[0]的值都是2010,但含義不一樣,如圖6-11所示。圖6-11a[i][j]的地址

說明:

(1)行地址+1的作用通俗地講是跳過一行,a+1將在a(值為2010)的基礎(chǔ)上跳過一行,即3個整型數(shù)據(jù),a+1的值為2010+3*4=2022。

(2)列地址+1的作用通俗地講是跳過一列,a[0]+1將在a[0](值為2010)的基礎(chǔ)上跳過一列,即1個整型數(shù)據(jù),a[0]+1的值為2010+1*4=2014。所以,a[0]+1與&a[0][1]等價。以此類推,a[i]+j與&a[i][j]等價。

前面介紹了*(a+i)與a[i]等價,所以a[0]+1和*(a+0)+1等價,都是&a[0][1],以此類推,a[i]+j和*(a+i)+j等價,都是&a[i][j]。

因此,如果要訪問二維數(shù)組元素a[i][j],可以表示為:

a[i][j]≡*(a[i]+j)≡*(*(a+i)+j)≡(*(a+i))[j]

其中a[i][j]為下標(biāo)表示法,其余均為地址表示法,其中考慮到a[i]≡*(a+i)。

【例6-3】用指針法實現(xiàn)輸入一個二維數(shù)組并輸出。

2.用于二維數(shù)組的指針變量

把二維數(shù)組a分解為一維數(shù)組a[0]和a[1]之后,可定義指向一維數(shù)組的指針變量(行指針變量),其定義的格式為

數(shù)據(jù)類型(*指針變量名)[一維數(shù)組元素個數(shù)];

其中:“數(shù)據(jù)類型”為所指數(shù)組的數(shù)據(jù)類型;“*”表示其后的變量是指針變量;“一維數(shù)組元素個數(shù)”表示二維數(shù)組分解為多個一維數(shù)組時,一維數(shù)組的長度,即二維數(shù)組的列數(shù)?!纠?-4】用指向二維數(shù)組的指針變量實現(xiàn)輸入一個二維數(shù)組并輸出。

6.2.3指針與字符串

在上一章中介紹了用字符數(shù)組處理字符串的方法,本節(jié)將介紹用指針處理字符串的方法。使用指針處理字符串會更加靈活、方便。引用字符串時,既可以逐個字符引用,也可以整體引用。

假設(shè)有如下定義和初始化程序:

chars[6]="Hello",*p="Hello";

其中:s是字符數(shù)組,最多存放6個字符;p是指向字符類型的指針變量,存放的是字符串常量的首地址。初始化后,效果如果6-12所示。圖6-12字符數(shù)組和字符指針

字符數(shù)組和字符指針都可以處理字符串,那么它們有什么區(qū)別呢?它們的區(qū)別見

表6-1。

【例6-5】用字符指針變量指向一個字符串,然后輸出該字符串。

6.2.4指針數(shù)組

如果數(shù)組的每個元素都是指針類型的數(shù)據(jù),則稱這種數(shù)組為指針數(shù)組。

指針數(shù)組的定義形式為:

數(shù)據(jù)類型*數(shù)組名[常量表達(dá)式]

例如:

int*p[4];

說明:由于[]比*優(yōu)先級高,因此p先與[]結(jié)合,表明p為數(shù)組名,數(shù)組p中包含4個元素。然后再與*結(jié)合,*表示此數(shù)組元素是指針類型,每個元素都指向一個整型變量,即每個元素相當(dāng)于一個指針變量。

6.2.5指針與動態(tài)內(nèi)存分配

通常情況下,在程序運(yùn)行之前程序中變量的個數(shù)和類型是確定的。但有時在程序運(yùn)行前無法預(yù)見需要占用多大的內(nèi)存空間,需要在運(yùn)行程序時根據(jù)具體情況向系統(tǒng)申請分配內(nèi)存空間,這種分配機(jī)制稱為動態(tài)內(nèi)存分配。C語言提供了一些內(nèi)存管理函數(shù),這些內(nèi)存管理函數(shù)可以按需要動態(tài)分配內(nèi)存空間,還可以把不再使用的內(nèi)存空間收回待用,提高了內(nèi)存資源的使用效率。

1.申請內(nèi)存空間函數(shù)malloc

調(diào)用形式:

(指針?biāo)笇ο蟮臄?shù)據(jù)類型*)malloc(sizeof(指針?biāo)笇ο蟮臄?shù)據(jù)類型)*個數(shù))

功能:在內(nèi)存的動態(tài)存儲區(qū)中申請一塊指定字節(jié)大小的連續(xù)空間。若申請成功,則返回指向所分配內(nèi)存空間的起始地址;若申請內(nèi)存空間不成功,則返回NULL(值為0)。該函數(shù)的返回值為(void*)類型,因此在具體使用時,要將該函數(shù)返回值轉(zhuǎn)換到特定指針類型,賦給一個指針變量。

2.計數(shù)動態(tài)內(nèi)容分配函數(shù)calloc()

調(diào)用形式:

(指針?biāo)笇ο蟮臄?shù)據(jù)類型*)calloc(個數(shù),sizeof(指針?biāo)笇ο蟮臄?shù)據(jù)類型))

功能:在內(nèi)存的動態(tài)存儲區(qū)中分配指定個數(shù)的連續(xù)空間,每一存儲空間的長度為sizeof求出的長度,并且分配后把存儲塊全部初始化為0值。如申請成功,則返回指向所分配內(nèi)存空間的起始地址;若申請內(nèi)存空間不成功,則返回NULL(值為0)。

3.釋放內(nèi)存空間函數(shù)free

調(diào)用形式:

free(指針變量名)

功能:釋放由動態(tài)內(nèi)存分配函數(shù)申請到的整塊內(nèi)存空間,指針變量名為指向要釋放空間的首地址。如果該指針變量是空指針,則free函數(shù)什么都不做。該函數(shù)無返回值。

例如:

free(p); /*釋放p指針?biāo)赶虻拇鎯臻g*/

為了有效利用動態(tài)存儲區(qū),在知道某個動態(tài)分配的存儲塊不再使用時,應(yīng)及時將它釋放。

6.3指?針?與?函?數(shù)

6.3.1指針及數(shù)組名作為函數(shù)參數(shù)指針及數(shù)組名作為函數(shù)的參數(shù)時,是以數(shù)據(jù)的地址作為實參調(diào)用該函數(shù),即作為參數(shù)傳遞的不是數(shù)據(jù)本身,而是數(shù)據(jù)對應(yīng)的地址,使實參和形參指向同一存儲單元。所以,調(diào)用函數(shù)與被調(diào)函數(shù)存取的將是相同的一組空間,即雙向的“地址”傳遞,也就是說函數(shù)調(diào)用后,實參指向的對象的值可能會發(fā)生變化。

如果實參是指針或數(shù)組名,則與之對應(yīng)的被調(diào)函數(shù)中的形參應(yīng)為指針變量或數(shù)據(jù)名,并且其數(shù)據(jù)類型必須與被傳遞參數(shù)的數(shù)據(jù)類型保持一致。實參與形參對應(yīng)關(guān)系有4種組合,見表6-2所示。

(1)實參和形參均為數(shù)組名。

(2)實參是數(shù)組名,形參是指針變量。

(3)實參是指針變量,形參是數(shù)組名。

(4)實參和形參均為指針變量。

【例6-7】利用指針做參數(shù)實現(xiàn)兩個數(shù)據(jù)的交換。

說明:調(diào)用swap函數(shù)時,實參是&a和&b,即把實參變量a和b的地址傳遞給形參指針變量x和y,即x和y分別指向了a和b。在函數(shù)里對指針?biāo)笇ο蟮膬?nèi)容進(jìn)行了交換,調(diào)用結(jié)束返回main函數(shù)后,a和b的內(nèi)容也交換了。

【例6-8】編寫一個字符串的復(fù)制函數(shù)。

說明:數(shù)組名傳給指針變量,即指針指向這片存儲單元的首地址,對指針?biāo)竷?nèi)容的操作就是對實參數(shù)組的操作。因此,函數(shù)調(diào)用后數(shù)組b的內(nèi)容改變了。

6.3.2指針作為函數(shù)的返回值

函數(shù)的返回值可以是各種基本數(shù)據(jù)類型,如整型、字符型和實型等,也可以是指針類型,這樣的函數(shù)稱為返回指針型的函數(shù)。

定義返回指針型的函數(shù)形式為:

數(shù)據(jù)類型*函數(shù)名(形參表)

例如:

int*fun(intx)

其中fun是函數(shù)名,x是形式參數(shù),形參類型為整型,函數(shù)名fun前面的數(shù)據(jù)類型int表示返回的指針指向整型變量,調(diào)用該函數(shù)后可以返回一個指向整型數(shù)據(jù)的指針(即地址)。

說明:函數(shù)fun兩邊的運(yùn)算符分別是*和(),其中()的優(yōu)先級高于*,因此fun先和()結(jié)合,表明fun是函數(shù)名;函數(shù)名前有一個*,表示此函數(shù)返回值類型是指針。

6.3.3指向函數(shù)的指針

程序中的每個函數(shù)經(jīng)過編譯后,其目標(biāo)代碼在內(nèi)存中是連續(xù)存放的,并被分配一個入口地址(即首地址)。C語言中的指針,不僅可以指向各種數(shù)據(jù)類型的變量和數(shù)組,而且還可以指向函數(shù)。C語言規(guī)定,函數(shù)名代表該函數(shù)的入口地址。如果把這個地址送給某個特定的指針變量,這個指針變量就指向了函數(shù),通過這個指針變量可以實現(xiàn)函數(shù)的調(diào)用。把這種指向函數(shù)的指針變量稱為“

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論