版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
C++“指針”學(xué)習建議
一.對于眾多人提出的C/C++中指針難學(xué)的問題做個總結(jié):
指針學(xué)習不好關(guān)鍵是概念不清造成的,說的簡單點就是書沒有認
真看,指針的學(xué)習猶如人在學(xué)習饒口令不多看多學(xué)多練是不行的,下
面是兩個很經(jīng)典的例子,很多書上都有,對于學(xué)習的重點在于理解*x
和x的理解,他們并不相同,*x所表示的其實就是變量a本身,x表
示的是變量a在內(nèi)存中的地址,如果想明白可以輸出觀察
cout<<*x"|"x;,當定義了int*x;后對x=&a的理解的問題。仔
細閱讀和聯(lián)系下面的兩個例子我想指針問題就不是難點了!
#include<stdio.h>
main()
(
inta,b;/*定義a,b兩個整形變量用于輸入兩個整數(shù)*/
int*point_l,*point_2,*temp_point;/*定義三個指針變量*/
scanf("%d,%d",&a,&b);/*格式化輸入a,b的值*/
point_l=&a;/*把指針變量point_l的值指向變量a的地址*/
point_2=&b;/*把指針變量point_2的值指向變量b的地址*/
if(a<b)
(
temp_point=point_l;/*這里的temp_point是用于臨時存儲
point_l的值也就是變量a的地址的*/
point_l=point_2;/*把point_2的值賦予point_l*/
point_2=temp_point;
/*由于point_l的值已經(jīng)改變無法找至1J,利用前面臨時存儲的也就
是temp_point找回原point_l的值賦予point_2,打到把point_l和
point_2值對換的目的*/
}
printf("%d,%cT,*point_l,*point_2);/*利用*point」和*point_2也
就是分辨指向b和a的方法把值顯示屏幕上*/
)
/*此題需要注意和了解是的此法并沒有改變變量a,b的值只是利
用指針變量分別存儲a和b的地址,然后再把那兩個指針變量的值對
換一下其實就是存儲在指針變量里面a與b的地址對換,在利用
*point_l和*point_2的方式把調(diào)換后的
值顯示出來這里的*point」實際就是a,此中算法并非真的改變
a,b的值,而是利用指針進行地址交換達到大小排序的目的.*/
#include<stdio.h>
main()
(
inta,b;/*定義a,b兩個整形變量用于輸入兩個整數(shù)*/
int*point_l,*point_2;/*定義三個指針變量*/
scanf("%d,%d",&a,&b);/*格式化輸入a,b的值*/
point_l=&a;/*把指針變量point_l的值指向變量a的地址*/
point_2=&b;/*把指針變量point_2的值指向變量b的地址*/
compositor(pointJL,point_2);/*調(diào)用自定義的排序涵數(shù),把a,b的地
址傳遞給point_l和point_2*/printf("%d,%cT,a,b);/*打印出a,b的值*/
}
staticcompositor(pl,p2)
int*pl,*p2;/*定義形式參數(shù)pl,p2為指針變量*/
(
inttemp;/*建立臨時存儲變量*/
if(*pl<*p2)/*如果*pl<p2,注意這里的*pl和*p2其實就是a
和b*/
(
temp=*pl;/*利用變量temp用于臨時存儲*pl和就是a的值*/
*pl=*p2;/*將*pl的值也就是a的值換成*p2的值也就是b的值,
等價于a=b*/
*p2=temp;/*將*p2的值也就是temp的值等價于b=temp*/
}
)
/*注意:此題與上題不同的是,直接改變了a于b的值達到真實改
變的目的*/
二.C++指針使用方法解惑
//voidClearList(LNode*&HL)w
仔細看一下這種聲明方式,確實有點讓人迷惑。
下面以voidfuncl(MYCLASS*&pBuildingElement);為例來說
明這個問題。在某種意義上,"*"和"&"是意思相對的兩個東西,
把它們放在一起有什么意義呢?。為了理解指針的這種做法,我們先
復(fù)習一下C/C++編程中無所不在的指針概念。我們都知道MYCLASS*
的意思:指向某個對象的指針,此對象的類型為MYCLASS。Voidfunci
(MYCLASS*pMyClass);〃例如:MYCLASS*p=newMYCLASS;
fund(p);
上面這段代碼的這種處理方法想必誰都用過,創(chuàng)建一個MYCLASS
對象,然后將它傳入funcl函數(shù)?,F(xiàn)在假設(shè)此函數(shù)要修改pMyClass:
voidfunci(MYCLASS*pMyClass)
(
DoSomething(pMyClass);
pMyClass=〃其它對象的指針
}
第二條語句在函數(shù)過程中只修改了pMyClass的值。并沒有修改
調(diào)用者的變量P的值。如果p指向某個位于地址
0x008a00的對象,當fund返回時,它仍然指向這個特定的對象。
(除非funcl有bug將堆弄亂了,完全有這種可能。)
現(xiàn)在假設(shè)你想要在funcl中修改p的值。這是你的權(quán)利。調(diào)用者
傳入一個指針,然后函數(shù)給這個指針賦值。以往一般都是傳雙指針,
即指針的指針,例如,CMyClass**o
MYCLASS*p=NULL;
fund(&p);
voidfunci(MYCLASS**pMyClass);
(
*pMyClass=newMYCLASS;
}
調(diào)用funcl之后,p指向新的對象。在COM編程中,你到處都會
碰到這樣的用法-例如在查詢對象接口的
Queryinterface函數(shù)中:
interfacelSomelnterface{
HRESULTQueryInterface(IID&iid,void**ppvObj);
};
LPSOMEINTERFACEp=NULL;
pOb->Querylnterface(IID_SOM曰NTERFACE,&p);
此處,p是SOMEINTERFACE類型的指針,所以&p便是指針
的指針,在QueryInterface返回的時候,如果調(diào)用成功,則變量p包
含一個指向新的接口的指針。
如果你理解指針的指針,那么你肯定就理解指針引用,因為它們
完全是一回事。如果你象下面這樣聲明函數(shù):voidfunci
(MYCLASS*&pMyClass);
pMyClass=newMYCLASS;
}
其實,它和前面所講得指針的指針例子是一碼事,只是語法有所
不同。傳遞的時候不用傳p的地址&p,而是直接傳p本身:
MYCLASS*p=NULL;
fund(p);
在調(diào)用之后,p指向一個新的對象。一般來講,引用的原理或多
或少就象一個指針,從語法上看它就是一個普通變量。所以只要你碰
到*&,就應(yīng)該想到**。也就是說這個函數(shù)修改或可能修改調(diào)用
者的指針,而調(diào)用者象普通變量一樣傳遞這個指針,不使用地址操作
符&。
至于說什么場合要使用這種方法,我會說,極少。MFC在其集合
類中用到了它一例如,CQbList,它是一個Cobjects指針列表。
ClassCObList:publicCobject{
〃獲取/修改指定位置的元素
Cobject*&GetAt(POSITIONposition);
Cobject*GetAt(POSITIONposition)const;
};
這里有兩個GetAt函數(shù),功能都是獲取給定位置的元素。區(qū)別何
在呢?
區(qū)別在于一個讓你修改列表中的對象,另一個則不行。所以如果
你寫成下面這樣:Cobject*pObj=mylist.GetAt(pos);
則pObj是列表中某個對象的指針,如果接著改變pObj的值:
pObj=pSomeOtherObj;
這并改變不了在位置pos處的對象地址,而僅僅是改變了變量
pObjo但是,如果你寫成下面這樣:Cobject*&rpObj=mylist.GetAt
(pos);
現(xiàn)在,rpObj是引用一個列表中的對象的指針,所以當改變rpObj
時,也會改變列表中位置pos處的對象地址-換句話說,替代了這個
對象。這就是為什么CObList會有兩個GetAt函數(shù)的緣故。一個可以
修改指針的值,另一個則不能。注意我在此說的是指針,不是對象本
身。這兩個函數(shù)都可以修改對象,但只有*&版本可以替代對象。
在C/C++中引用是很重要的,同時也是高效的處理手段。所以要
想成為C/C++高手,對引用的概念沒有透徹的理解和熟練的應(yīng)用是不
行的。
三.數(shù)據(jù)指針
在C/C++語言中一直是很受寵的;幾乎找不到一個不使用指針的
C/C++應(yīng)用。用于存儲數(shù)據(jù)和程序的地址,這是指針的基本功能。用
于指向整型數(shù),用整數(shù)指針(int*);指向浮點數(shù)用浮點數(shù)指針(float*);
指向結(jié)構(gòu),用對應(yīng)的結(jié)構(gòu)指針(structxxx*);指向任意地址,用無類型
指針(void*)。
有時候,我們需要一些通用的指針。在C語言當中,(void*)可以
代表一切;但是在C++中,我們還有一些比較特殊的指針,無法用
(void*)來表示。事實上,在C++中,想找到一個通用的指針,特別是
通用的函數(shù)指針簡直是一個“不可能任務(wù)二
C++是一種靜態(tài)類型的語言,類型安全在C++中舉足輕重。在C
語言中,你可以用void*來指向一切;但在C++中,void*并不能指向
一切,就算能,也失去了類型安全的意義了。類型安全往往能幫我們
找出程序中潛在的一些BUGo
下面我們來探討一下,C++中如何存儲各種類型數(shù)據(jù)的指針。
C++指針探討(一,)數(shù)據(jù)指針沐楓網(wǎng)志
L數(shù)據(jù)指針
數(shù)據(jù)指針分為兩種:常規(guī)數(shù)據(jù)指針和成員數(shù)據(jù)指針
1.1常規(guī)數(shù)據(jù)指針
這個不用說明了,和C語言一樣,定義、賦值是很簡單明了的。
常見的有:int*,double*等等。
如:intvalue=123;
int*pn=&value;
1.2成員數(shù)據(jù)指針
有如下的結(jié)構(gòu):
structMyStruct
(
intkey;
intvalue;
};
現(xiàn)在有一個結(jié)構(gòu)對象:
MyStructme;
MyStruct*pMe=&me;
我們需要value成員的地址,我們可以:
int*pValue=&me.value;
〃或
int*pValue=&pMe->value;
當然了,這個指針仍然是屬于第一種范籌--常規(guī)數(shù)據(jù)指針。
好了,我們現(xiàn)在需要一種指針,它指向MyStruct中的任一數(shù)據(jù)
成員,那么它應(yīng)該是這樣的子:
intMyStruct::*pMV=&MyStruct::value;
〃或
intMyStruct::*pMK=&MyStruct::key;
這種指針的用途是用于取得結(jié)構(gòu)成員在結(jié)構(gòu)內(nèi)的地址。我們可以
通過該指針來訪問成員數(shù)據(jù):intvalue=pMe->*pMV;〃取得pMe的
value成員數(shù)據(jù)。
intkey=me.*pMK;〃取得me的key成員數(shù)據(jù)。
那么,在什么場合下會使用到成員數(shù)據(jù)指針呢?
確實,成員指針本來就不是一種很常用的指針。不過,在某些時
候還是很有用處的。我們先來看看下面的一個函數(shù):
intsum(MyStruct*objs/intMyStruct::*pm,intcount)
intresult=O;
for(inti=0;i<count;++i)
result+=objs[i].*pm;
returnresult;
}
這個函數(shù)的功能是什么,你能看明白嗎?它的功能就是,給定
count個MyStruct結(jié)構(gòu)的指針,計算出給定成員數(shù)據(jù)的總和。有點拗
口對吧?看看下面的程序,你也許就明白了:
MyStructme[10]=
(
{1,2},{3,4},{5,6},億8},{9,10},{11,12},{13,14},{15,16},{17,18},{19,20}
};
intsum_value=sum(me/&MyStruct::value/10);
〃計算10個MyStruct結(jié)構(gòu)的value成員的總和:sum_value值為
110intsum_key=sum(me/&MyStruct::key/10);
〃計算10個MyStruct結(jié)構(gòu)的key成員的總和:sum_key值為
100(2+4+6+8++20)(1+3+5+7++19)也許,你覺得用常規(guī)指針也可以做到,
而且更易懂。0k,沒問題:intsum(MyStruct*objs,intcount)
(
intresult=O;
for(inti=0;i<count;++i)
result+=objs[i].value;
returnresult;
}
你是想這么做嗎?但這么做,你只能計算value,如果要算key
的話,你要多寫一個函數(shù)。有多少個成員需要計算的話,你就要寫多
少個函數(shù),多麻煩啊。指針
四.C++指針使用
在下列函數(shù)聲明中,為什么要同時使用*和&符號?以及什
么場合使用這種聲明方式?
voidfuncl(MYCLASS*&pBuildingElement);論壇中經(jīng)常有人問
到這樣的問題。
本文試圖通過一些實際的指針使用經(jīng)驗來解釋這個問題。
仔細看一下這種聲明方式,確實有點讓人迷惑。在某種意義上,
"”和"&"是意思相對的兩個東西,把它們放在一起有什么意義
呢?。為了理解指針的這種做法,我們先復(fù)習一下C/C++編程中無所
不在的指針概念。我們都知道MYCLASS*的意思:指向某個對象的指
針,此對象的類型為MYCLASSovoidfuncl(MYCLASS*pMyClass);
〃例如:MYCLASS*p=newMYCLASS;
funcl(p);
上面這段代碼的這種處理方法想必誰都用過,創(chuàng)建一個MYCLASS
對象,然后將它傳入funcl函數(shù)?,F(xiàn)在假設(shè)此函數(shù)要修改pMyClass:
voidfuncl(MYCLASS*pMyClass)
DoSomething(pMyClass);
pMyClass=〃其它對象的指針
}
第二條語句在函數(shù)過程中只修改了pMyClass的值。并沒有修改
調(diào)用者的變量p的值。如果p指向某個位于地址0x008a00
的對象,當funci返回時,它仍然指向這個特定的對象。(除非
funcl有bug將堆弄亂了,完全有這種可能。)
現(xiàn)在假設(shè)你想要在funcl中修改p的值。這是你的權(quán)利。調(diào)用者
傳入一個指針,然后函數(shù)給這個指針賦值。以往一般都是傳雙指針,
即指針的指針,例如,CMyClass**oMYCLASS*p=NULL;
funcl(&p);
voidfuncl(MYCLASS**pMyClass);
(
*pMyClass=newMYCLASS;
)
調(diào)用funcl之后,p指向新的對象。在COM編程中,你到處都會
碰到這樣的用法-例如在查詢對象接口的Queryinterface函數(shù)中:
interfacelSomelnterface{
HRESULTQuerylnterface(IID&iid,void**ppvObj);
};
LPSOMEINTERFACEp=NULL;
pOb->Querylnterface(IID_SOMEINTERFACE/&p);
此處,p是SOM日INTERFACE類型的指針,所以&p便是指針
的指針,在Queryinterface返回的時候,如果調(diào)用成功,則變量p包
含一個指向新的接口的指針。
如果你理解指針的指針,那么你肯定就理解指針引用,因為它們
完全是一回事。如果你象下面這樣聲明函數(shù):
voidfuncl(MYCLASS*&pMyClass);
(
pMyClass=newMYCLASS;
}
其實,它和前面所講得指針的指針例子是一碼事,只是語法有所
不同。傳遞的時候不用傳p的地址&p,而是直接傳p本身:
MYCLASS*p=NULL;
funcl(p);
在調(diào)用之后,P指向一個新的對象。一般來講,引用的原理或多
或少就象一個指針,從語法上看它就是一個普通變量。所以只要你碰
到*&,就應(yīng)該想到**。也就是說這個函數(shù)修改或可能修改調(diào)用
者的指針,而調(diào)用者象普通變量一樣傳遞這個指針,不使用地址操作
符&。
至于說什么場合要使用這種方法,我會說,極少。MFC在其集合
類中用到了它-例如,CObList,它是一個CObjects指針列表。
classCObList:publicCObject{
〃獲取/修改指定位置的元素
CObject*&GetAt(POSITIONposition);
CObject*GetAt(POSITIONposition)const;
};
這里有兩個GetAt函數(shù),功能都是獲取給定位置的元素。區(qū)別何
在呢?
區(qū)別在于一個讓你修改列表中的對象,另一個則不行。所以如果
你寫成下面這樣:CObject*pObj=mylist.GetAt(pos);
則pObj是列表中某個對象的指針,如果接著改變pObj的值:
pObj=pSomeOtherObj;
這并改變不了在位置pos處的對象地址,而僅僅是改變了變量
pObjo但是,如果你寫成下面這樣:
CObject*&rpObj=mylist.GetAt(pos);
現(xiàn)在,rpObj是引用一個列表中的對象的指針,所以當改變rpObj
時一,也會改變列表中位置pos處的對象地址-換句話說,替代了這個
對象。這就是為什么CObList會有兩個GetAt函數(shù)的緣故。一個可以
修改指針的值,另一個則不能。注意我在此說的是指針,不是對象本
身。這兩個函數(shù)都可以修改對象,但只有*&版本可以替代對象。
在C/C++中引用是很重要的,同時也是高效的處理手段。所以要
想成為C/C++高手,對引用的概念沒有透徹的理解和熟練的應(yīng)用是不
行的。
五.新手學(xué)習之淺析C/C++中的指針
在學(xué)習c/c+過程中,指針是一個比較讓人頭痛的問題,稍微不注
意將會是程序編譯無法通過,甚至造成死機。在程序設(shè)計過程中,指
針也往往是產(chǎn)生隱含bug的原因。下面就來談?wù)勚羔樀膽?yīng)用以及需要
注意的一些問題,里面也許就有你平時沒有注意到的問題,希望能幫
助各位讀者理解好指針。
一、我們先來回憶一下指針的概念吧,方便下面的介紹
指針是存放地址值的變量或者常量。例如:inta=l;&a就表
示指針常量(“&”表示取地址運算符,也即引用)。int*b,b表
示的是指針變量(注意,是b表示指針變量而不是*b),*表示要說明
的是指針變量。大家注意int*b[2]和int(*b)⑵是不同的,int是表
示一個指針數(shù)組,而int(*b)⑵表示含有兩個元素的int指針,這里
要注意運算優(yōu)先級問題,有助于理解指針問題。在這里大概介紹基本
概念就夠了,至于具體使用方法,如賦值等,很多書都有介紹,我就
不多說了。
二、應(yīng)用以及注意的問題
1、理解指針的關(guān)鍵所在——對指針類型和指針所指向的類型的
理解
①、指針類型:可以把指針名字去掉,剩下的就是這個指針
例如:int*a;〃指針類型為int*
int**a;〃指針類型為int**
int*(*a)[8];〃指針類型為int*(*)[8]
②、指針所指向的類型:是指編譯器將把那一片內(nèi)存所看待成的
類型。這里只要把指針聲明語句中的指針名字和名字右邊的“*”號
去掉就可以了,剩下的就是指針所指向的類型。
我之所以把他們放在第一位,是因為弄清楚他們是學(xué)C/C++指針
的重點,正確理解他們才能使你打好C/C++的編程基礎(chǔ)。
2、指針的應(yīng)用——傳遞參數(shù)。
其實它可以相當于隱式的返回值,這就比return的方法更加靈活
了,可以返回更多的值,看看下面的例子自然就明白了:
#include"iostream.h"
voidexample(int*al,int&bl,intcl)
(
*al*=3;
++bl;
++cl;
}
voidmain()
(
int*a;
intb,c;
*a=6;
b=7;c=10;
example(a,b,c);
cout<<"*a="<<*a<
cout<<"b="<
cout<<"c="<
}
輸出:*a=18
b=8
c=10
注意到?jīng)]有,*a和b的值都改變了,而c沒有變。這是由于al
是指向*a(=6)的指針,也即與a是指向同一個地址,所以當al指
向的值改變了,*a的值也就改變了。在函數(shù)中的參數(shù)使用了引用
(int&bl),bl是b的別名,也可
以把它當作特殊的指針來理解,所以b的值會改變。函數(shù)中的參
數(shù)intel只是在函數(shù)中起作用,當函數(shù)結(jié)束時候便消失了,所以在main
()中不起作用。
3、關(guān)于全局變量和局部變量的一個問題先不廢話了,先看看程
序:
#include,/iostream.h//
inta=5;
int*examplel(intb)
a+=b;
return&a;
}
int*example2(intb)
(
intc=5;
b+=c;
return&b;
}
voidmain()
(
int*al=examplel(10);
int*bl=example2(10);
cout<<wal=w<<*al<
cout<<wbl=w<<*bl<
)
輸出結(jié)果:
al=15
bl=4135
*bl怎么會是4135,而不是15呢?是程序的問題?沒錯吧?
由于a是全局變量,存放在全局變量的內(nèi)存區(qū),它一直是存在的;
而局部變量則是存在于函數(shù)的棧區(qū),當函數(shù)example2()調(diào)用結(jié)束
后便消失,是b指向了一個不確定的區(qū)域,產(chǎn)生指針懸掛。
下面是對examplel()和example2()的反匯編(用TC++3.0
編譯):
examplel():
pushbp;入棧
movbp;sp
movax,[bp+04];傳遞參數(shù)
add[OOAA],ax;相力口
movaxQOAA;返回了結(jié)果所在的地址
popbp;恢復(fù)棧,出棧
ret;退出函數(shù)
example2():
pushbp;入棧
movbp,sp
subsp,02
movwordptr[bp-02]z0005
movax,[bp-02];傳遞參數(shù)
add[bp+04],ax;相加
leaax,[bp+04];問題就出在這里
movsp,bp
popbp;恢復(fù)棧,出棧
ret;退出函數(shù)
對比之后看出來了吧?ax應(yīng)該是存儲的是結(jié)果的地址。而在
example?()中,返回的卻是[bp+04]的內(nèi)容,因此指針指向了一個不
確定的地方,由此產(chǎn)生的指針懸掛。examplel()中,ax返回了正確
的結(jié)果的地址。4、內(nèi)存問題:使用指針注意內(nèi)存的分配和邊界。使
用指針過程中應(yīng)該給變量一個適當?shù)目臻g,以免產(chǎn)生不可見的錯誤。
請看以下代碼:
#include,/iostream.h//
voidmain()
(
char*al;
char*a2;
cin>>al;
cin>>a2;
cout<<wal=/7<
cout<<wa2=w<
}
輸入:abc
123
輸出:
al=123
a2=
Nullpointerassignment
指針指向了“空二解決辦法就是分配適當?shù)膬?nèi)存給這兩個字符
串。修正后的代碼如下:
#include//iostream.hw
voidmain()
(
char*al;
char*a2;
al=newchar[10];
a2=newchar[10];
cin>>al;
cin>>a2;
cout<<wal=w<
cout<<,,a2=//<
delete(a1);注意,別忘了要釋放內(nèi)存空間
delete(a2);
}
到此就能輸出正確的結(jié)果了。分配了適當?shù)膬?nèi)存之后要注意釋放
內(nèi)參空間,同時還應(yīng)該注意不要超出所分配的內(nèi)存
的大小,否則會有溢出現(xiàn)象產(chǎn)生,導(dǎo)致不可預(yù)料的結(jié)果。
5、關(guān)于特殊的指針——引用
引用有時候應(yīng)用起來要比指針要靈活,用它做返回的時候是不產(chǎn)
生任何變量的副本的這樣減小了內(nèi)存的占用,提高執(zhí)行的速度。引用
使用起來要比指針好理解,比較直觀。當引用作為參數(shù)時,不會改變
參數(shù)的地址,因此可以作為左值。
下面請看一個例子:
#include//iostream.h/,
charch[5]=〃ABCD〃;
char&example(intb)
(
returnch;
}
voidmain()
(
cout<<"ch="<
example(2)=wcw;
cout<<wch=/?<
}
輸出結(jié)果:
ch=ABCD
ch=ABcD
在實際編程過程中,可以靈活地引用或指針,盡量提高程序的可
讀性和執(zhí)行效率。
三、小結(jié):
指針是學(xué)習C/C++的重點難點,主要原因是指針較為抽象,不容
易理解。使用指針千萬要明白讓指針指向什么地方,如何讓指針指向
正確的地方。在深入系統(tǒng)底層之中需要應(yīng)用到大量的指針,因此需要
理解好指針的基本概念,例如:指針類型和指針所指向的類型。平時
應(yīng)該對留心觀察,了解程序的工作過程,必要時候可以對程序進行反
匯編,加深對指針的理解,這種方法同樣適合學(xué)別的編程方面的知識。
四、結(jié)束:
指針的應(yīng)用是很廣泛的,利用指針可以做很多事情,要成為一個
好的程序員,必須對指針有比較深刻的了解。寫本文的目的在于讓大
家對指針有更深一層的了解,提高指針的應(yīng)用能力,內(nèi)容大都是我在
實際編程中遇到的問題。相信能給大家一定的幫助。
六.C++中關(guān)于指針入門的最好的文章
什么是指針?
其實指針就像是其它變量一樣,所不同的是一般的變量包含的是
實際的真實的數(shù)據(jù),而指針是一個指示器,它告訴程序在內(nèi)存的哪塊
區(qū)域可以找到數(shù)據(jù)。這是一個非常重要的概念,有很多程序和算法都
是圍繞指針而設(shè)計的,如鏈表。
開始學(xué)習
如何定義一個指針呢?就像你定義一個其它變量一樣,只不過你
要在指針名字前加上一個星號。我們來看一個例子:下面這個程序定
義了兩個指針,它們都是指向整型數(shù)據(jù)。
int*pNumberOne;
int*pNumberTwo;
你注意到在兩個變量名前的“P”前綴了嗎?這是程序員通常在
定義指針時的一個習慣,以提高便程序的閱讀性,表示這是個指針。
現(xiàn)在讓我們來初始化這兩個指針:
pNumberOne=&some_number;
pNumberTwo=&some_other_number;
&號讀作“什么的地址”,它表示返回的是變量在內(nèi)存中的
地址而不是變量本身的值。在這個例子中,pNumberOne等于
的地址,所以現(xiàn)在指向
some_numberpNumberOnesome_numbero
如果現(xiàn)在我們在程序中要用到some_number,我們就可以使用
pNumberOneo
我們來學(xué)習一個例子:
在這個例子中你將學(xué)到很多,如果你對指針的概念一點都不了解,
我建議你多看兒遍這個例子,指針是個很復(fù)雜的東西,但你會很快掌
握它的。
這個例子用以增強你對上面所介紹內(nèi)容的了解。它是用C編寫的
(注:原英文版是用C寫的代碼,譯者重新用C++改寫寫了所有代碼,
并在DEVC++和VC++中編譯通過!)
#include<iostream.h>
voidmain()
{〃聲明變量:
intnNumber;
int*pPointer;
〃現(xiàn)在給它們賦值:
nNumber=15;
pPointer=&nNumber;
〃打印出變量nNumber的值:
cout<<"nNumberisequalto:"<<nNumber<<endl;
〃現(xiàn)在通過指針改變nNumber的值:
*pPointer=25;
〃證明nNumber已經(jīng)被上面的程序改變
〃重新打印出nNumber的值:
cout<<"nNumberisequalto:"<<nNumber<<endl;
}
通讀一下這個程序,編譯并運行它,務(wù)必明白它是怎樣工作的。
如果你完成了,準備好,開始下一小節(jié)。
陷井!
試一下,你能找出下面這段程序的錯誤嗎?
#include<iostream.h>
int*pPointer;
voidSomeFunction();
intnNumber;
nNumber=25;
〃讓指針指向nNumber:
pPointer=&nNumber;
}
voidmain()
(
SomeFunction();〃為pPointer賦值
〃為什么這里失敗了?為什么沒有得到25
cout<<"Valueof*pPointer:"<<*pPointer<<endl;
}
這段程序先調(diào)用了SomeFunction函數(shù),創(chuàng)建了個叫nNumber的
變量,接著讓指針pPointer指向了它??墒菃栴}出在哪兒呢?當函數(shù)
結(jié)束后,nNumber被刪掉了,
因為這一個局部變量。局部變量在定義它的函數(shù)執(zhí)行完后都會被
系統(tǒng)自動刪掉。也就是說當SomeFunction函數(shù)返回主函數(shù)main()時,
這個變量已經(jīng)被刪掉,但pPointer還指著變量曾經(jīng)用過的但現(xiàn)在已不
屬于這個程序的區(qū)域。如果你還不明白,你可以再讀讀這個程序,注
意它的局部變量和全局變量,這些概念都非常重要。
但這個問題怎么解決呢?答案是動態(tài)分配技術(shù)。注意這在C和
C++中是不同的。由于大多數(shù)程序員都是用C++,所以我用到的是C++
中常用的稱謂。
動態(tài)分配
動態(tài)分配是指針的關(guān)鍵技術(shù)。它是用來在不必定義變量的情況下
分配內(nèi)存和讓指針去指向它們。盡管這么說可能會
讓你迷惑,其實它真的很簡單。下面的代碼就是一個為一個整型
數(shù)據(jù)分配內(nèi)存的例子:
int*pNumber;
pNumber=newint;
第一行聲明一個指針pNumber。第二行為一個整型數(shù)據(jù)分配一個
內(nèi)存空間,并讓pNumber指向這個新內(nèi)存空間。下面是一個新例,
這一次是用double雙精型:
double*pDouble;
pDouble=newdouble;
這種格式是一個規(guī)則,這樣寫你是不會錯的。
但動態(tài)分配又和前面的例子有什么不同呢?就是在函數(shù)返回或
執(zhí)行完畢時,你分配的這塊內(nèi)存區(qū)域是不會被刪除的所以我們現(xiàn)在可
以用動態(tài)分配重寫上面的程序:
#include<iostream.h>
int*pPointer;
voidSomeFunction()
{〃讓指針指向一個新的整型
pPointer=newint;
*pPointer=25;
}
voidmain()
(
SomeFunction();〃為pPointer賦值
cout<<"Valueof*pPointer:"<<*pPointer<<endl;
}
通讀這個程序,編譯并運行它,務(wù)必理解它是怎樣工作的。當
SomeFunction調(diào)用時,它分配了一個內(nèi)存,并讓pPointer指向它。這
一次,當函數(shù)返回時,新的內(nèi)存區(qū)域被保留下來,所以pPointer始終
指著有用的信息,這是因為了動態(tài)分配。但是你再仔細讀讀上面這個
程序,雖然它得到了正確結(jié)果,可仍有一個嚴重的錯誤。
分配了內(nèi)存,別忘了回收
太復(fù)雜了,怎么會還有嚴重的錯誤!其實要改正并不難。問題是:
你動態(tài)地分配了一個內(nèi)存空間,可它絕不會被自動刪除。也就是說,
這塊內(nèi)存空間會一直存在,直到你告訴電腦你已經(jīng)使用完了??山Y(jié)果
是,你并沒有告訴電腦你已不再需要這塊內(nèi)存空間了,所以它會繼續(xù)
占據(jù)著內(nèi)存空間造成浪費,甚至你的程序運行完畢,其它程序運行時
它還存在。當這樣的問題積累到一定程度,最終將導(dǎo)致系統(tǒng)崩潰。所
以這是很重要的,在你用完它以后,請釋放它的空間,如:
deletepPointer;
這樣就差不多了,你不得不小心。在這你終止了一個有效的指針
(一個確實指向某個內(nèi)存的指針)。下面的程序,
它不會浪費任何的內(nèi)存:
#include<iostream.h>
int*pPointer;
voidSomeFunction()
{〃讓指針指向一個新的整型
pPointer=newint;
*pPointer=25;
}
voidmain()
(
SomeFunction();〃為pPointer賦值
cout<<"Valueof*pPointer:"<<*pPointer<<endl;
deletepPointer;
}
只有一行與前一個程序不同,但就是這最后一行十分地重要。如
果你不刪除它,你就會制造一起“內(nèi)存漏洞”,而讓內(nèi)存逐漸地泄漏。
(譯者:假如在程序中調(diào)用了兩次SomeFunction,你又該如何修改這個
程序呢?請讀者自己思考)
傳遞指針到函數(shù)
傳遞指針到函數(shù)是非常有用的,也很容易掌握。如果我們寫一個
程序,讓一個數(shù)加上5,看一看這個程序完整嗎?:
#include<iostream.h>
voidAddFive(intNumber)
(
Number=Number+5;
}
voidmain()
(
intnMyNumber=18;
cout<<"Myoriginalnumberis"<<nMyNumber<<endl;
AddFive(nMyNumber);
cout<<"Mynewnumberis"<<nMyNumber<<endl;
}
問題出在函數(shù)AddFive里用到的Number是變量nMyNumber的
一個副本而傳遞給函數(shù),而不是變量本身。因此,"Number=Number+5"
這一行是把變量的副本加了5,而原始的變量在主函數(shù)main()里依然
沒變。試著運行這個程序,〃得到了結(jié)果23嗎?問題出在哪兒?
自己去體會一下。要解決這個問題,我們就要傳遞一個指針到函
數(shù),所以我們要修改一下函數(shù)讓它能接受指針:把
'voidAddFive(intNumberj'改成
'voidAddFive(int*Number)';o下面就是改過的程序,注意函
數(shù)調(diào)用時要用&號,以表示傳遞的是指針:
#include<iostream.h>
voidAddFive(int*Number)
(
*Number=*Number+5;
}
voidmain()
(
intnMyNumber=18;
cout
七.我眼中的指針-學(xué)習指針不可少的好文章我眼中的指針-學(xué)
習指針不可少的好文章
為初學(xué)者服務(wù)。這是我的帖子的宗旨。我也是個初學(xué)者(強調(diào)了
無數(shù)遍了),我以我的理解把初學(xué)者覺得難懂的東西用淺顯的語言寫
出來。由于小學(xué)時語文沒學(xué)好,所以竭盡全力也未必能達到這個目的。
盡力而為吧。
指針是c和C++中的難點和重點。我只精通dos下的basiCoc語
言的其它各種特性,在basic中都有類似的東西。只有指針,是baisc
所不具備的。指針是c的靈魂。
我不想重復(fù)大多數(shù)書上說得很清楚的東西,我只是把我看過的書
中說得不清楚或沒有說,而我又覺得我理解得有點道理的東西寫出來。
我的目的是:
lo通過寫這些東西,把我腦袋中關(guān)于c的模糊的知識清晰化。
2o給初學(xué)者們一點提示。
3o賺兒個經(jīng)驗值。(因為貼這些東西沒有灌水之嫌啊)
第一章。指針的概念
指針是一個特殊的變量,它里面存儲的數(shù)值被解釋成為內(nèi)存里的
一個地址。要搞清一個指針需要搞清指針的四方面的內(nèi)容:指針的類
型,指針所指向的類型,指針的值或者叫指針所指向的內(nèi)存區(qū),還有
指針本身所占據(jù)的內(nèi)存區(qū)。讓我們分
別說明。先聲明兒個指針放著做例子:
例一:
(l)int*ptr;
(2)char*ptr;
(3)int**ptr;
(4)int(*ptr)[3];
(5)int*(*ptr)[4];
如果看不懂后兒個例子的話,請參閱我前段時間貼出的文?
如何理解c和C++的復(fù)雜類型聲明>>。
lo指針的類型。
從語法的角度看,你只要把指針聲明語句里的指針名字去掉,剩
下的部分就是這個指針的類型。這是指針本身所具有的類型。讓我們
看看例一中各個指針的類型:
⑴int*ptr;〃指針的類型是int*
(2)char*ptr;〃指針的類型是char*
⑶int**ptr;〃指針的類型是int**
⑷int(*ptr)[3];〃指針的類型是int(*)⑶
(5)int*(*ptr)[4];〃指針的類型是int*(*)[4]
怎么樣?找出指針的類型的方法是不是很簡單?
2o指針所指向的類型。
當你通過指針來訪問指針所指向的內(nèi)存區(qū)時、指針所指向的類型
決定了編譯器將把那片內(nèi)存區(qū)里的內(nèi)容當做什么來看待。從語法上看,
你只須把指針聲明語句中的指針名字和名字左邊的指針聲明符*去掉,
剩下的就是指針所指向的類型。例如:
⑴int*ptr;〃指針所指向的類型是int
(2)char*ptr;〃指針所指向的的類型是char
(3)int**ptr;〃指針所指向的的類型是int*
⑷int(*ptr)[3];〃指針所指向的的類型是int()⑶
⑸int*(*ptr)⑷;〃指針所指向的的類型是int*()[4]
在指針的算術(shù)運算中,指針所指向的類型有很大的作用。
指針的類型(即指針本身的類型)和指針所指向的類型是兩個概念。
當你對C越來越熟悉時,你會發(fā)現(xiàn),把與指針攪和在一起的"類型"這
個概念分成"指針的類型"和"指針所指向的類型"兩個概念,是精通指
針的關(guān)鍵點之一。我看了不少書,發(fā)現(xiàn)有些寫得差的書中,就把指針
的這兩個概念攪在一起了,所以看起書來前后矛盾,越看越糊涂。
3o指針的值,或者叫指針所指向的內(nèi)存區(qū)或地址。
指針的值是指針本身存儲的數(shù)值,這個值將被編譯器當作一個地
址,而不是一個一般的數(shù)值。在32位程序里,所有類型的指針的值
都是一個32位整數(shù),因為32位程序里內(nèi)存地址全都是32位長。指
針所指向的內(nèi)存區(qū)就是從指針的值所代表的那個內(nèi)存地址開始,長度
為sizeof(指針所指向的類型)的一片內(nèi)存區(qū)。以后,我們說一個指針
的值是XX,就相當于說該指針指向了以XX為首地址的一片內(nèi)存區(qū)域;
我們說一個指針指向了某塊內(nèi)存區(qū)域,就相當于說該指針的值是這塊
內(nèi)存區(qū)域的首地址。
指針所指向的內(nèi)存區(qū)和指針所指向的類型是兩個完全不同的概
念o在例一中,指針所指向的類型已經(jīng)有了,但由于指針還未初始化,
所以它所指向的內(nèi)存區(qū)是不存在的,或者說是無意義的。
以后,每遇到一個指針,都應(yīng)該問問:這個指針的類型是什么?
指針指向的類型是什么?該指針指向了哪里?
4o指針本身所占據(jù)的內(nèi)存區(qū)。
指針本身占了多大的內(nèi)存?你只要用函數(shù)sizeof(指針的類型)測
一下就知道了。在32位平臺里,指針本身占據(jù)了4個字節(jié)的長度。
指針本身占據(jù)的內(nèi)存這個概念在判斷一個指針表達式是否是左值時
很有用。
第二章。指針的算術(shù)運算
指針可以加上或減去一個整數(shù)。指針的這種運算的意義和通常的
數(shù)值的加減運算的意義是不一樣的。例如:例二:
lochara[20];
2oint*ptr=a;
3optr++;
在上例中,指針ptr的類型是int*,它指向的類型是int,它被初始
化為指向整形變量a。接下來的第3句中,指針ptr被加了1,編譯
器是這樣處理的:它把指針ptr的值加上了sizeof(int),在32位程序
中,是被加上了4。由于地址是用字節(jié)做單位的,故ptr所指向的地
址由原來的變量a的地址向高地址方向增加了4個字節(jié)。
由于char類型的長度是一個字節(jié),所以,原來ptr是指向數(shù)組a
的第0號單元開始的四個字節(jié),此時指向了數(shù)組a中從第4號單元開
始的四個字節(jié)。我們可以用一個指針和一個循環(huán)來遍歷一個數(shù)組,看
例子:
例三:
例三:
intarray[20];
int*ptr=array;
〃此處略去為整型數(shù)組賦值的代碼。
for(i=0;i<20;i++)
(*ptr)++;
ptr++;
}
這個例子將整型數(shù)組中各個單元的值加lo由于每次循環(huán)都將
八.指針詳解
第一章。指針的概念
指針是一個特殊的變量,它里面存儲的數(shù)值被解釋成為內(nèi)存里的
一個地址。
要搞清一個指針需要搞清指針的四方面的內(nèi)容:指針的類型,指
針所指向的類型,指針的值或者叫指針所指向的內(nèi)存區(qū),
還有指針本身所占據(jù)的內(nèi)存區(qū)。讓我們分別說明。先聲明兒個指
針放著做例子:
例一:
(l)int*ptr;
(2)char*ptr;
(3)int**ptr;
(4)int(*ptr)[3];
(5)int*(*ptr)[4];
lo指針的類型。
從語法的角度看,你只要把指針聲明語句里的指針名字去掉,剩
下的部分就是這個指針的類型。這是指針本身所具有的類型。讓我們
看看例一中各個指針的類型:
(l)int*ptr;〃指針的類型是int*
(2)char*ptr;〃指針的類型是char*
⑶int**ptr;〃指針的類型是int**
(4)int(*ptr)⑶;〃指針的類型是int(*)[3]
⑸int*(*ptij[4];〃指針的類型是int*(*)[4]
怎么樣?找出指針的類型的方法是不是很簡單?
2o指針所指向的類型。
當你通過指針來訪問指針所指向的內(nèi)存區(qū)時,指針所指向的類型
決定了編譯器將把那片內(nèi)存區(qū)里的內(nèi)容當做什么來看待。從語法上看,
你只須把指針聲明語句中的指針名字和名字左邊的指針聲明符*去掉,
剩下的就是指針所指向的類型。例如:
(l)int*ptr;〃指針所指向的類型是int
(2)char*ptr;〃指針所指向的的類型是char
⑶int**ptr;〃指針所指向的的類型是int*
⑷int(*ptr)[3];〃指針所指向的的類型是int()⑶
⑸int*(*ptr)⑷;〃指針所指向的的類型是int*()[4]
在指針的算術(shù)運算中,指針所指向的類型有很大的作用。
指針的類型(即指針本身的類型)和指針所指向的類型是兩個概念。
當你對C越來越熟悉時,你會發(fā)現(xiàn),把與指針攪和在一起的"類型"這
個概念分成"指針的類型"和"指針所指向的類型"兩個概念,是精通指
針的關(guān)鍵點之一。我看了不少書,發(fā)現(xiàn)有些寫得差的書中,就把指針
的這兩個概念攪在一起了,所以看起書來前后矛盾,越看越糊涂。
3o指針的值,或者叫指針所指向的內(nèi)存區(qū)或地址。
指針的值是指針本身存儲的數(shù)值,這個值將被編譯器當作一個地
址,而不是一個一般的數(shù)值。在32位程序里,所有類型的指針的值
都是一個32位整數(shù),因為32位程序里內(nèi)存地址全都是32位長。指
針所指向的內(nèi)存區(qū)就是從指針的值所代表的那個內(nèi)存地址開始,長度
為sizeof(指針所指向的類型)的一片內(nèi)存區(qū)。以后,我們說一個指針
的值是XX,就相當于說該指針指向了以XX為首地址的一片內(nèi)存區(qū)域;
我們說一個指針指向了某塊內(nèi)存區(qū)域,就相當于說該指針的值是這塊
內(nèi)存區(qū)域的首地址。指針所指向的內(nèi)存區(qū)和指針所指向的類型是兩個
完全不同的概念。在例一中,指針所指向的類型已經(jīng)有了,但由于指
針還未初始化,所以它所指向的內(nèi)存區(qū)是不存在的,或者說是無意義
的。以后,每遇到一個指針,都應(yīng)該問問:這個指針的類型是什么?
指針指向的類型是什么?該指針指向了哪里?
4o指針本身所占據(jù)的內(nèi)存區(qū)。
指針本身占了多大的內(nèi)存?你只要用函數(shù)sizeof(指針的類型)測
一下就知道了。在32位平臺里,指針本身占據(jù)了4個字節(jié)的長度。
指針本身占據(jù)的內(nèi)存這個概念在判斷一個指針表達式是否是左值時
很有用。
第二章。指針的算術(shù)運算
指針可以加上或減去一個整數(shù)。指針的這種運算的意義和通常的
數(shù)值的加減運算的意義是不一樣的。例如:例二:
lochara[20];
2oint*ptr=a;
3optr++;
在上例中,指針ptr的類型是int*,它指向的類型是int,它被初始
化為指向整形變量a。接下來的第3句中,指針ptr被加了1,編譯
器是這樣處理的:它把指針ptr的值加上了sizeof(int),在32位程序
中,是被加上了4。由于地址是用字節(jié)做單位的,故ptr所指向的地
址由原來的變量a的地址向高地址方向增加了4個字節(jié)。
由于char類型的長度是一個字節(jié),所以,原來ptr是指向數(shù)組a
的第0號單元開始的四個字節(jié),此時指向了數(shù)組a中從第4號單元開
始的四個字節(jié)。我們可以用一個指針和一個循環(huán)來遍歷一個數(shù)組,看
例子:
例三:
intarray[20];
int*ptr=array;
〃此處略去為整型數(shù)組賦值的代碼。
for(i=0;i<20;i++)
(
(*ptr)++;
ptr++;
)
這個例子將整型數(shù)組中各個單元的值加lo由于每次循環(huán)都將指
針ptr加1,所以每次循環(huán)都能訪問數(shù)組的下一個單元。再看例子:
例四:
lochara[20];
2oint*ptr=a;
3optr+=5;
在這個例子中,ptr被加上了5,編譯器是這樣處理的:將指針
ptr的值加上5乘sizeof(int),在32位程序中就是加上了5乘4=20。
由于地址的單位是字節(jié),故現(xiàn)在的ptr所指向的地址比起加5后的ptr
所指向的地址來說,向高地址方向移動了20個字節(jié)。在這個例子中,
沒加5前的ptr指向數(shù)組a的第0號單元開始的四個字節(jié),加5后,
ptr已經(jīng)指向了數(shù)組a的合法范圍之外了。雖然這種情況在應(yīng)用上會
出問題,但在語法上卻是可以的。這也體現(xiàn)出了指針的靈活性。
如果上例中,ptr是被減去5,那么處理過程大同小異,只不過
ptr的值是被減去5乘sizeof(int),新的ptr指向的地址將比原來的ptr
所指向的地址向低地址方向移動了20個字節(jié)。
總結(jié)一下,一個指針ptrold加上一個整數(shù)n后,結(jié)果是一個新的
指針ptrnew,
ptrnew的類型和ptrold的類型相同,ptmew所指向的類型和
ptrold所指向的類型也相同。ptmew的值將比ptrold的值增加了n乘
sizeof(ptrold所指向的類型)個字節(jié)。就是說,ptrnew所指向的內(nèi)存區(qū)
將比ptrold所指向的內(nèi)存區(qū)向高地址方向移動了n乘sizeof(ptrold所
指向的類型)個字節(jié)。一個指針ptrold減去一個整數(shù)n后,結(jié)果是一
個新的指針ptrnew,ptrnew的類型和ptrold的類型相同,ptrnew所
指向的類型和ptrold所指向的類型也相同。ptrnew的值將比ptrold
的值減少了n乘sizeof(ptrold所指向的類型)個字節(jié),就是說,ptrnew
所指向的內(nèi)存區(qū)將比ptrold所指向的內(nèi)存區(qū)向低地址方向移動了n乘
sizeof(ptrold所指向的類型)個字節(jié)。
第三章。運算符&和*
這里&是取地址運算符,*是…書上叫做"間接運算符"。
&a的運算結(jié)果是一個指針,指針的類型是a的類型加個*,指針
所指向的類型是a的類型,指針所指向的地址嘛,那就是a的地址。
*p的運算結(jié)果就五花八門了??傊?P的結(jié)果是P所指向的東西,這
個東西有這些特點:它的類型是p指向的類型,它所占用的地址是p
所指向的地址。
例五:
inta=12;
intb;
int*p;
int**ptr;
p=&a;〃&a的結(jié)果是一個指針,類型是int*,指向的類
型是int,指向的地址是a的地址。
*p=24;〃*p的結(jié)果,在這里它的類型是int,它所占用的地址是p
所指向的地址,顯然,*p就是變量a。
ptr=&p;//&p的結(jié)果是個指針,該指針的類型是p的類
型加個*,在這里是int**。該指針所指向的類型是p的類型,這里是
該指針所指向的地址就是指針自己的地址。
int*op
*ptr=&b;〃*ptr是個指針,&b的結(jié)果也是個指針,且這
兩個指針的類型和所指向的類型是一樣的,所以用&b來給*ptr
賦值就是毫無問題的了。
**ptr=34;//*ptr的結(jié)果是ptr所指向的東西,在這里是一個指針,
對這個指針再做一次*運算,結(jié)果就是一個int類型的變量。
第四章。指針表達式。
一個表達式的最后結(jié)果如果是一個指針,那么這個表達式就叫指
針表達式。下面是一些指針表達式的例子:例六:
inta,b;
intarray[10];
int*pa;
pa=&a;//&a是一個指針表達式。
int**ptr=&pa;//&pa也是一個指針表達式。
*ptr=&b;//*ptr和&b都是指針表達式。
pa=array;
pa++;〃這也是指針表達式。
例七:
char*arr[20];
char**parr=arr;〃如果把arr看作指針的話,arr也是指針表達式
char*str;
str=*parr;//*parr是指針表達式
str=*(parr+l);〃*(parr+l)是指針表達式
str=*(parr+2);〃*(parr+2)是指針表達式
由于指針表達式的結(jié)果是一個指針,所以指針表達式也具有指針
所具有的四個要素:指針的類型,指針所指向的類型,指針指向的內(nèi)
存區(qū),指針自身占據(jù)的內(nèi)存。
好了,當一個指針表達式的結(jié)果指針已經(jīng)明確地具有了指針自身
占據(jù)的內(nèi)存的話,這個指針表達式就是一個左值,否則就不是一個左
值。在例七中,&a不是一個左值,因為它還沒有占據(jù)明確的內(nèi)
存。*ptr是一個左值,因為*ptr這個指針已經(jīng)占據(jù)了內(nèi)存,其實*ptr
就是指針pa,既然pa已經(jīng)在內(nèi)存中有了自己的位置,那么*ptr當然
也有了自己的位置。
第五章。數(shù)組和指針的關(guān)系
數(shù)組的數(shù)組名其實可以看作一個指針??聪吕?/p>
例八:
intarray[10]={0,l,2,3,4/5,6,7,8/9}/value;
value=array[O];〃也可寫成:value=*array;
value=array[3];〃也可寫成:value=*(array+3);
value=array[4];〃也可寫成:value=*(array+4);
上例中,一般而言數(shù)組名array代表數(shù)組本身,類型是
但如果把array看做指針的話,它指向數(shù)組的第0個單元,類型是int*,
所指向的類型是數(shù)組單元的類型即int。因此*array等于。就一點也不
奇怪了。同理,array+3是一個指向數(shù)組第3個單元的指針,所以
*(array+3)等于3。其它依此類推。
例九:
char*str[3]={
"Hello^hisisasample!",
"Hi,goodmorning.”,
"Helloworld"
};
chars[80];
strcpy(s,str[O]);〃也可寫成strcpy(s/str);
strcpy(s,str⑴);〃也可寫成strcpy(s,*(str+l));
strcpy(s,str[2]);〃也可寫成strcpy(s,*(str+2));
上例中,str是一個三單元的數(shù)組,該數(shù)組的每個單元都是一個
指針,這些指針各指向一個字符串。把指針數(shù)組名str當作一個指針
的話,它指向數(shù)組的第。號單元,它的類型是char**,它指向的類型
是char*。*str也是一個指針,它的類型是char*,它所指向的類型是
char,它指向的地址是字符串"Hegthisisasample!"的第一個字符的地
址,即''H''的地址。str+1也是一個指針,它指向
數(shù)組的第1號單元,它的類型是char**,它指向的類型是char*o*(str+l)
也是一個指針,它的類型
溫馨提示
- 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)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 二零二五年度廠區(qū)生態(tài)綠化養(yǎng)護與生態(tài)農(nóng)業(yè)合同3篇
- 2024版工地施工方與投資方協(xié)議樣本版B版
- 2024年網(wǎng)絡(luò)廣告代理服務(wù)最高額合同
- 學(xué)生個人學(xué)期總結(jié)
- 婦女節(jié)活動標語15篇
- 出科小結(jié)帶教老師評語
- 2025版合同管理知識庫建設(shè)與維護合同3篇
- 二零二五年度個人股權(quán)交易糾紛調(diào)解與轉(zhuǎn)讓協(xié)議3篇
- 奔向未來為主題演講稿范文800字(18篇)
- 2024承建工程項目承包合同書
- 2024午托承包合同-校園內(nèi)學(xué)生午休服務(wù)協(xié)議3篇
- 馬克思主義基本原理+2024秋+試題 答案 國開
- 蘇州大學(xué)《線性代數(shù)與解析幾何》2023-2024學(xué)年第一學(xué)期期末試卷
- 《地震災(zāi)害及其防治》課件
- 2024年版電商平臺入駐商家服務(wù)與銷售分成合同
- 蜜雪冰城合同范例
- 小紅書種草營銷師(初級)認證考試真題試題庫(含答案)
- LPG液化氣充裝站介質(zhì)分析操作規(guī)程 202412
- 養(yǎng)老院環(huán)境衛(wèi)生保潔方案
- 2024年WPS計算機二級考試題庫350題(含答案)
- 2024年5G網(wǎng)絡(luò)覆蓋工程分包合同
評論
0/150
提交評論