linuxC中指針的使用.ppt_第1頁
linuxC中指針的使用.ppt_第2頁
linuxC中指針的使用.ppt_第3頁
linuxC中指針的使用.ppt_第4頁
linuxC中指針的使用.ppt_第5頁
已閱讀5頁,還剩21頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

linux C中指針的使用,學(xué)號: 姓名:,1、指針的概念 指針是一個特殊的變量,它里面存儲的數(shù)值被解釋成為內(nèi)存里的一個地址。 把一個變量所在的內(nèi)存單元的地址保存在另外一個內(nèi)存單元中,保存地址的這個內(nèi)存單元稱為指針。 重點(diǎn):指針的四方面的內(nèi)容:指針的類型、指針?biāo)赶虻念愋?、指針的?或者叫指針?biāo)赶虻膬?nèi)存區(qū))、指針本身所占據(jù)的內(nèi)存區(qū)。,(1)指針的類型 判斷指針類型的方法:把指針聲明語句里的指針名字去掉,剩下的部分就是這個指針的類型。 如:int*ptr;/指針的類型是int* char*ptr;/指針的類型是char* int*ptr;/指針的類型是int* int(*ptr)3;/指針的類型是int(*)3 int*(*ptr)4;/指針的類型是int*(*)4,.(3)指針的值-或者叫指針?biāo)赶虻膬?nèi)存區(qū)或地址 指針的值是指針本身存儲的數(shù)值,這個值將被編譯器當(dāng)作一個地址,而不是一個一般的數(shù)值。 在32位程序里,所有類型的指針的值都是一個32位整數(shù),因?yàn)?2位程序里內(nèi)存地址全都是32位長。 指針?biāo)赶虻膬?nèi)存區(qū)就是從指針的值所代表的那個內(nèi)存地址開始,長度為sizeof(指針?biāo)赶虻念愋?的一片內(nèi)存區(qū)。,(4)指針本身所占據(jù)的內(nèi)存區(qū) 只要用函數(shù)sizeof(指針的類型)測一下就可以知道。在32位平臺里,指針本身占據(jù)了4個字節(jié)的長度。在64位平臺上指針變量都占8個字節(jié)。 注意: sizeof(指針的名稱)測到的是指針自身類型的大小。,2、指針中&和* &是取地址運(yùn)算符,*號是指針間接尋址運(yùn)算符。&i表示取變量 i 的地址。*pi表示取指針pi 所指向的變量的值。 &運(yùn)算符的操作數(shù)必須是左值,因?yàn)橹挥凶笾挡疟硎疽粋€內(nèi)存單元,才會有地址, 運(yùn)算結(jié)果是指針類型。 *運(yùn)算符的操作數(shù)必須是指針類型,運(yùn)算結(jié)果可以做左值。,3、指針類型轉(zhuǎn)換 指針之間可以相互賦值,也可以用一個指針初始化另一個指針,例如: int *ptri = pi; 或者: int *ptri; ptri = pi; 本質(zhì)上就是把變量pi所保存的地址值賦 給變量ptri。 用一個指針給另一個指針賦值時要注意,兩個指針必須是同一類型的。不是同一類型時可以進(jìn)行強(qiáng)制類型轉(zhuǎn)換然后賦值。,例如: float f=12.3; float *fptr= 不對。因?yàn)橹羔榩的類型是int *,它指向的類型是int。表達(dá)式&f 的結(jié)果是一個指針,指針的類型是float *,它指向的類型是float。,強(qiáng)制類型轉(zhuǎn)換。 p=(int*) 如果有一個指針p,我們需要把它的類型和所指向的類型改為TYPE* 、TYPE, 那么語法格式是: (TYPE *)p; 這樣強(qiáng)制類型轉(zhuǎn)換的結(jié)果是一個新指針,該新指針的類型是TYPE *,它指向的類型是TYPE,它指向的地址就是原指針指向的地址。而原來的指針p的一切屬性都沒有被修改。,4、算數(shù)運(yùn)算 指針可以加上或減去一個整數(shù)。指針的這種運(yùn)算的意義和通常的數(shù)值的加減運(yùn)算的意義是不一樣的,以單元為單位。 例1:char a20; int *ptr=(int *)a; /強(qiáng)制類型轉(zhuǎn)換并不會改變a的類型 ptr+; 第3句中,指針ptr被加了1,編譯器是這樣處理的:它把指針ptr的值加上了sizeof(int),在32位程序中,是被加上了4,因?yàn)樵?2位程序中,int占4個字節(jié)。 由于地址是用字節(jié)做單位的,故ptr所指向的地址由原來的變量a的地址向高地址方向增加了4個字節(jié)。由于char類型的長度是一個字節(jié),所以,原來ptr是指向數(shù)組a的第0號單元開始的四個字節(jié),此時指向了數(shù)組a中從第4號單元開始的四個字節(jié)。,一個指針ptrold 加(減)一個整數(shù)n 后,結(jié)果是一個新的指針ptrnew,ptrnew的類型和ptrold的類型相同,ptrnew所指向的類型和ptrold所指向的類型也相同。ptrnew的值將比ptrold的值增加(減少)了n乘sizeof(ptrold所指向的類型)個字節(jié)。 兩個指針不能進(jìn)行加法運(yùn)算,這是非法操作,沒意義。 兩個指針可以進(jìn)行減法操作,但必須類型相同 。 指針之間的進(jìn)行比較運(yùn)算比的是地址。,5、指針表達(dá)式 一個表達(dá)式的結(jié)果如果是一個指針,那么這個表達(dá)式就叫指針表式。 由于指針表達(dá)式的結(jié)果是一個指針,所以指針表達(dá)式也具有指針?biāo)哂械乃膫€要素:指針的類型,指針?biāo)赶虻念愋?,指針指向的?nèi)存區(qū),指針自身占據(jù)的內(nèi)存。 當(dāng)一個指針表達(dá)式的結(jié)果指針已經(jīng)明確地具有了指針自身占據(jù)的內(nèi)存的話,這個指針表達(dá)式就是一個左值,否則就不是一個左值。,6、數(shù)組和指針的關(guān)系 數(shù)組的數(shù)組名其實(shí)可以看作一個指針。 聲明了一個數(shù)組TYPE arrayn,則數(shù)組名稱array就有了兩重含義:第一,它代表整個數(shù)組,它的類型是TYPEn;第二 ,它是一個常量指針,該指針的類型是TYPE*,該指針指向的類型是TYPE,也就是數(shù)組單元的類型,該指針指向的內(nèi)存區(qū)就是數(shù)組第0號單元,該指針自己占有單獨(dú)的內(nèi)存區(qū),注意它和數(shù)組第0號單元占據(jù)的內(nèi)存區(qū)是不同的。該指針的值是不能修改的,即類似array+的表達(dá)式是錯誤的。,例:int array10=0,1,2,3,4,5,6,7,8,9,value; value=array0; /也可寫成:value=*array; value=array3; /也可寫成:value=*(array+3); value=array4; /也可寫成:value=*(array+4); 上例中,一般而言數(shù)組名array代表數(shù)組本身,類型是int10,但如果把a(bǔ)rray看做指針的話,它指向數(shù)組的第0個單元,類型是int*,所指向的類型是數(shù)組單元的類型即int。array+3是一個指向數(shù)組第3個單元的指針,所以*(array+3)等于3。 字符串相當(dāng)于是一個數(shù)組,在內(nèi)存中以數(shù)組的形式儲存,只不過字符串是一個數(shù)組常量,內(nèi)容不可改變,且只能是右值.如果看成指針的話,他即是常量指針,也是指針常量.,7、指針和結(jié)構(gòu)類型的關(guān)系 可以聲明一個指向結(jié)構(gòu)類型對象的指針。例子如下: struct MyStruct int a; int b; int c; ; struct MyStruct ss=20,30,40;/聲明了結(jié)構(gòu)對象ss,并把ss 的成員初始化為20,30 和40。 struct MyStruct *ptr=/聲明了一個指向結(jié)構(gòu)對象ss的指針。它的類型是MyStruct *,它指向的類型是MyStruct.。 通過指針p訪問結(jié)構(gòu)體成員可以寫成(*ptr).a、(*ptr).b和(*ptr).c,為了書寫方便,C 語言提供了-運(yùn)算符,也可以寫成ptr-a和ptr-b、ptr-b。,8、指針與函數(shù)的關(guān)系 可以把一個指針聲明成為一個指向函數(shù)的指針。函數(shù)指針存放的就是函數(shù)的入口地址。 int fun1(char *,int); int (*pfun1)(char *,int); pfun1=fun1; int a=(*pfun1)(“abcdefg“,7); /通過函數(shù)指針調(diào)用函數(shù)。可以把指針作為函數(shù)的形參。在函數(shù)調(diào)用語句中,可以用指針表達(dá)式來作為實(shí)參。 一個函數(shù)如果使用了指針作為形參,那么在函數(shù)調(diào)用語句的實(shí)參和形參的結(jié)合過程中,必須保證類型一致 ,否則需要強(qiáng)制轉(zhuǎn)換.,分析一下變量f的類型聲明int(*pfun1)( char*,int),pfun1首先跟*號結(jié)合在一起, 因此是一個指針。(*pfun1)外面是一個函數(shù)原型的格式,參數(shù)是char *和int,返回值是int,所以pfun1是指向這種函數(shù)的指針。,9、指針的安全問題 (1)意外改寫數(shù)據(jù) 例子:char a; int *ptr= 該例子完全可以通過編譯,并能執(zhí)行。但是,第3句對指針ptr進(jìn)行自加1運(yùn)算后,ptr指向了和整形變量a相鄰的高地址方向的一塊存儲區(qū)。這塊存儲區(qū)里是什么?我們不知道。有可能它是一個非常重要的數(shù)據(jù),甚至可能是一條代碼。而第4句竟然往這片存儲區(qū)里寫入一個數(shù)據(jù)!這是嚴(yán)重的錯誤。,為了避免這種情況可以使用const限定符。 const int *a; int const *a; 這兩種寫法是一樣的,a是一個指向const int型的指針,a所指向的內(nèi)存單元 不可改寫,所以(*a)+是不允許的,但a可以改寫,所以a+是允許的。 int * const a; a是一個指向int型的const指針,*a是可以改寫的,但a不允許改寫。 int const * const a; a是一個指向const int型的const指針,因此*a和a都不允許改寫。,指向非const變量的指針或者非const變量的地址可以傳給指向const變量的指 針,編譯器可以做隱式類型轉(zhuǎn)換,例如: char c = a; const char *pc = 但是,指向const變量的指針或者const變量的地址不可以傳給指向非const變量的指針,以免透過后者意外改寫了前者所指向的內(nèi)存單元。,(2)出現(xiàn)“野指令 ” 有一種情況需要特別注意,定義一個指針類型的局 部變量而沒有初始化: int main(void) int *p; . *p = 0; . 在堆棧上分配的變量初始值是不確定的,也就是說指針p所指向的內(nèi)存地址是不確定的,后面用*p訪問不確定的地址就會導(dǎo)致不確定的后果。于是很容易出現(xiàn)”野指令“。,我們常把指向不確定地址的指針稱為“野指針“(Unbound Pointer),為避免出現(xiàn)野指針,在定義指針變量時就應(yīng)該給它明確的初值,或 者把它初始化為NULL: int main(void) int *p = NULL; . *p = 0; . ,NULL在C標(biāo)準(zhǔn)庫的頭文件stddef.h中定義:#define NULL (void *)0) 就是把地址0轉(zhuǎn)換成指針類型,稱為空指針,它的特殊之處在于,操作系統(tǒng)不會 把任何數(shù)據(jù)保存在地址0及其附近,也不會把地址00xfff的頁面映射到物理內(nèi) 存,所以任何對地址0的訪問都會立刻導(dǎo)致段錯誤

溫馨提示

  • 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

提交評論