版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認(rèn)領(lǐng)
文檔簡介
1、C程序設(shè)計語言,第5章 指針與數(shù)組,孫志崗,計算機內(nèi)的存儲部件,活動中的所有指令和數(shù)據(jù)都保存在內(nèi)存內(nèi) 速度快,但是掉電即失 可以隨機訪問 只要指名要訪問的內(nèi)存單元的地址,就可以立即訪問到該單元 地址是一個無符號整數(shù)(通常用16進制數(shù)),其字長與主機相同 內(nèi)存中的每個字節(jié)都有唯一的一個地址,內(nèi)存(Random Access Memory)地址(Address),指針的故事,“該程序執(zhí)行了非法操作,即將關(guān)閉” 這種錯誤幾乎全是由指針和數(shù)組導(dǎo)致的 黑客攻擊服務(wù)器利用的bug絕大部分都是指針和數(shù)組造成的 有些非計算機專業(yè)的人,盡量避免使用指針,指針的故事,鐵桿C/C+程序員最摯愛的武器:指針 指針造就
2、了C/C+的高效和強大 很多不可能的任務(wù)由指針完成 main()char*a=main()char*a=%c%s%c;printf(a,34,a,34);printf(a,34,a,34);,關(guān)于指針的原則,學(xué)習(xí)原則 一定要學(xué)會 其實通常的應(yīng)用很簡單 就是一個變量 復(fù)雜的應(yīng)用也不建議使用 使用原則 永遠(yuǎn)要清楚每個指針指向了哪里 永遠(yuǎn)要清楚指針指向的位置是什么,數(shù)組(Array),若干類型相同的相關(guān)數(shù)據(jù)湊到一起,就是數(shù)組 定義 類型 數(shù)組名整型常數(shù)1整型常數(shù)2 整型常數(shù)n; int a64; 使用 a00、a12、a53 每個元素都是一個普通變量 下標(biāo)可以是任意整型表達(dá)式 數(shù)組的各個元素在內(nèi)存中
3、分布在一起,分布規(guī)律是array.c 思考一下一維和三維數(shù)組怎么分布呢?,從類型的角度理解數(shù)組,int a10; 定義了一個有10個int類型元素的數(shù)組 a的類型可以看作int10(只是看作,語法并不允許這么定義: int10 a) int a2010; 定義了一個有20個int10類型元素數(shù)組 a0、 a1a9的類型是int10,所以a00、 a01a199的類型是int int a302010; 這個呢? 這種特性決定了數(shù)組元素在內(nèi)存的分布規(guī)律,也解釋了數(shù)組的很多語法現(xiàn)象,數(shù)組初始化,數(shù)組定義后的初值仍然是隨機數(shù),一般需要我們來初始化 int a5 = 12, 34, 56 ,78 ,9
4、; int a5 = 0 ; int a = 11, 22, 33, 44, 55 ; 數(shù)組大小最好用宏來定義,以適應(yīng)未來可能的變化 #define SIZE 10int aSIZE;,數(shù)組的使用,數(shù)組的下標(biāo)都是從0開始 對數(shù)組每個元素的使用與普通變量無異 可以用任意表達(dá)式作為下標(biāo),動態(tài)決定訪問哪個元素 for (i=0; iSIZE; i+) ai = 2 * i; 下標(biāo)越界是大忌! 使用大于最大下標(biāo)的下標(biāo),將訪問數(shù)組以外的空間。那里的數(shù)據(jù)不是我們所想定的情況,可能帶來嚴(yán)重后果 有時,故意越界訪問數(shù)組會起到特別效果,但一定要對自己在做什么了如指掌 sizeof可以用來獲得數(shù)組所占字節(jié)數(shù) si
5、zeof(a) sizeof(a0),數(shù)組的用處與特點,保存大量同類型的相關(guān)數(shù)據(jù) 快速地隨機訪問 一旦定義,不能再改變大小 在編譯階段就確定了數(shù)組的大小 數(shù)組名幾乎就是一個指針,指針(Pointer),int *p; 定義了一個指針變量p,簡稱指針p p是變量,int*是類型 變量都占用內(nèi)存空間,p的大小是sizeof(int*) p用來保存地址。此時這個地址是哪呢(p指向哪呢)? int i;p = ,指針,指針也是數(shù)據(jù)類型。指向不同數(shù)據(jù)類型的指針,分別為不同的數(shù)據(jù)類型 int*、float*、char*、int*、int* 指針指向非其定義時聲明的數(shù)據(jù)類型,將引起warning void*
6、類型的指針可以指向任意類型的變量 指針在初始化時一般int *p=NULL; NULL表示空指針,即無效指針 但它只是邏輯上無效,并不是真正地?zé)o效 如果指針指向一個非你控制的內(nèi)存空間,并對該空間進行訪問,將可能造成危險,p = ,指針與數(shù)組,數(shù)組名可以看作一個指針 只是不能修改這個指針的指向 常指針 int a10; a的類型是int10 a的類型也是int* 指針可當(dāng)作數(shù)組名使用,反之亦然 int *p, a10;p = a;p1 = 0;*a = 0;,指針運算,int* p=NULL;p+;/* p的值會是多少? */ 指針的加減運算是以其指向的類型的字長為單位的 int *p, a10
7、;p = a; *(p+3) 等價于 a3 p+; *p 等價于 a1,指針運算,int *p, *q, a10;p = a;q = 運算法則 只能進行加減和關(guān)系運算 只能同類型指針之間或指針與整數(shù)之間運算,“類型”本不存在,存儲器在保存數(shù)據(jù)時并不關(guān)心數(shù)據(jù)的類型 完全以二進制方式工作 我們向計算機發(fā)出的指令說明了某塊內(nèi)存里數(shù)據(jù)的類型 一塊內(nèi)存內(nèi)保存著(61 62 63 64)16 以char類型看待每個字節(jié): abcd 以float類型看待每個字節(jié): 16777999408082104000000.000000 以int類型看待每個字節(jié): 1684234849,依天屠龍,強強聯(lián)手,int ma
8、in(void) int a = 0, 1, 2, 3, 4, 5, 6, 7, 8; int i; unsigned char *p; p = (unsigned char*)a; /* 類型強轉(zhuǎn)了 */ for (i=0; isizeof(a); i+) PrintHexChar(pi); /* 把指針當(dāng)數(shù)組用 */ putchar( ); 指針強轉(zhuǎn)后,可以把一塊內(nèi)存當(dāng)作另一種類型來處理 強強聯(lián)手,我們可以隨意控制任意內(nèi)存,god.c,指針與函數(shù),指針既然是數(shù)據(jù)類型,自然可以做函數(shù)的參數(shù)和返回值的類型 指針做參數(shù)的經(jīng)典例子: main() int x, y; swap(x, y); voi
9、d swap(int x, int y) int temp; temp = x; x = y; y = temp;,Not Work,指針做參數(shù),main() int x, y; swap(,這里的函數(shù)調(diào)用過程還是“實參” 的內(nèi)容復(fù)制到“形參” ,千萬不要理解成什么“傳引用調(diào)用”,指針做返回值,int* foo(void)int a = 100;return 永遠(yuǎn)不要把局部變量的地址作為返回值返回,這是極端錯誤的!,指針做返回值,printf(%s, GetInput();.char* GetInput(void)char str100;scanf(%s, str);return str; c
10、har string30;printf(%s, GetInput(string); . char* GetInput(char* str)scanf(%s, str);return str;,三個月使用scanf目睹之怪現(xiàn)狀,int i;scanf(%d, i); /* 這樣會如何?*/ int i;scanf(%f, /* 這樣呢?*/,i的值被當(dāng)作地址。例如,i的值如果是100,那么輸入的整數(shù)就會從地址100開始寫入內(nèi)存,輸入被當(dāng)作float,以float的二進制形式寫到i所在的內(nèi)存空間,輸入以int的二進制形式寫到c所在的內(nèi)存空間。c所占內(nèi)存不足以放下一個int,其后的空間也被覆蓋,數(shù)組
11、做參數(shù),和指針一回事兒 void ProcessArray(int* a). void ProcessArray(int a).,這里給定元素個數(shù)有意義嗎?,動態(tài)分配內(nèi)存,在 和中均定義了下面的函數(shù) void* malloc(size_t size); size_t是在中定義的數(shù)據(jù)類型,就是一個unsigned int 向系統(tǒng)申請大小為size的內(nèi)存塊,把指向首地址的指針返回。如果申請不成功,返回NULL void free(void* block); 釋放由malloc()申請的內(nèi)存塊。block是指向此塊的指針 malloc申請的內(nèi)存,在被free之前,程序的任何部分都可以使用 當(dāng)然,要使
12、用必須得到指向它的指針,動態(tài)分配內(nèi)存,如果malloc()申請的內(nèi)存不被free()程序就退出,將產(chǎn)生內(nèi)存泄露(Memory Leak) “內(nèi)存泄露”一詞類似“原料泄露”。泄露出去的原料不能被利用,導(dǎo)致生產(chǎn)過程中原料不足 malloc()時,系統(tǒng)找到一塊未占用的內(nèi)存,將其標(biāo)記為已占用,然后把地址返回,表明此程序占用此塊內(nèi)存,其它程序不能再用它 free()時,系統(tǒng)標(biāo)記此塊內(nèi)存為未占用,本程序不能繼續(xù)使用,所有程序可以申請使用 如果malloc()之后不free(),此塊內(nèi)存將永遠(yuǎn)不會被任何程序使用,就好像這塊內(nèi)存泄露出去一樣,防止內(nèi)存泄露之道,在需要的時候才malloc,并盡量減少malloc
13、的次數(shù) 能用自動變量解決的問題,就不要用malloc來解決 malloc一般在大塊內(nèi)存分配和動態(tài)內(nèi)存分配時使用 malloc本身的執(zhí)行效率就不高,所以過多的malloc會使程序性能下降 可以重復(fù)利用malloc申請到的內(nèi)存 盡量讓malloc和與之配套的free在一個函數(shù)內(nèi) 盡量把malloc集中在函數(shù)的入口處,free集中在函數(shù)的出口處 以上做法只能盡量降低產(chǎn)生泄露的概率。完全杜絕內(nèi)存泄露,關(guān)鍵要靠程序員的細(xì)心與責(zé)任感,字符串(String)與字符數(shù)組、字符指針,字符串 一串以0結(jié)尾的字符在C語言中被看作字符串 用雙引號括起的一串字符是字符串常量,C語言自動為其添加0終結(jié)符 Hello wo
14、rld! 把字符串常量作為表達(dá)式直接使用,得到的值是該常量的地址 C語言并沒有為字符串提供任何專門的表示法,完全使用字符數(shù)組和字符指針來處理 字符數(shù)組 每個元素都是字符類型的數(shù)組 char string100; 字符指針 指向字符類型的指針 char* p; 數(shù)組和指針可以等同看待,上面三者本質(zhì)上是一回事,字符串處理函數(shù),在中定義了若干專門的字符串處理函數(shù) strcpy: string copy char *strcpy(char *dest, const char *src); strlen: string length size_t strlen(const char *s); strca
15、t: string combination char *strcat(char *dest, const char *src); strcmp: string comparison int strcmp(const char *s1, const char *s2); stricmp: string comparison ignoring case int stricmp(const char *s1, const char *s2);,0作為字符串終結(jié)符的天生缺陷,假若交給這些字符串處理函數(shù)的字符串沒有0會如何? 0很關(guān)鍵,如果沒有,那么這些處理函數(shù)會一直進行處理直到遇到一個0為止。此時可能
16、已經(jīng)把內(nèi)存弄得亂七八糟 ANSI C定義了一些“n族”字符處理函數(shù),包括strncpy、strncat、strncmp、strnicmp等,通過增加一個參數(shù)來限制處理的最大長度,指針、數(shù)組以及其它的類型混合,基本數(shù)據(jù)類型 int、long、char、short、float、double 指針是一種數(shù)據(jù)類型 是從其它類型派生的類型 XX類型的指針 數(shù)組也是一種數(shù)據(jù)類型 是從其它類型派生的類型 每個元素都有一個類型 任何類型都可以做指針或者數(shù)組的基礎(chǔ)類型 它們自己也可以做彼此或自己的基礎(chǔ)類型,命令行參數(shù),通過命令行參數(shù),使用戶可以根據(jù)需要來決定我們的程序干什么、怎么干 main(int argc,
17、 char* argv) 當(dāng)你把main函數(shù)寫成這樣時 argc的值為程序執(zhí)行時參數(shù)的數(shù)目(包括命令本身) argvX為指向每個參數(shù)的字符指針,指向函數(shù)的指針,int (*pfunc) (int, int) 定義了一個函數(shù)指針pfunc,它指向的函數(shù)必須是:返回值為int類型,有兩個int類型的參數(shù) int f1(int a, int b);int f2(int x, int y); pfunc = f1;(*pfunc)(1, 2); pfunc = f2;(*pfunc)(1, 2);,qsort,void qsort(void *base, size_t nelem, size_t width, int(*fcmp)(const void *, const void *) ); 定義在中 用“快速排序”算法對base所指向的數(shù)據(jù)進行排序。每個數(shù)據(jù)占width個字節(jié),共有nelem個 fcmp是指向用戶自己定義的函數(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)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 單位管理制度呈現(xiàn)大全【人事管理】
- 三角形的面積推導(dǎo)課件
- 第4單元 民族團結(jié)與祖國統(tǒng)一 測試卷-2021-2022學(xué)年部編版八年級歷史下冊
- DBJT 13-317-2019 裝配式輕型鋼結(jié)構(gòu)住宅
- 《電鍍錫工藝學(xué)》課件
- 2024年大學(xué)生攝影大賽活動總結(jié)
- 《焊接基本知識》課件
- 中小學(xué)家長會122
- 美術(shù):源起與影響
- 醫(yī)療行業(yè)專業(yè)技能培訓(xùn)體會
- 2020年10月自考00094外貿(mào)函電試題及答案含解析
- 中等職業(yè)學(xué)校教研教改工作總結(jié)
- 甲狀腺細(xì)針穿刺細(xì)胞學(xué)檢查課件
- 醫(yī)療廢物管理人員及相關(guān)工作人員培訓(xùn)制度(15篇范文)
- 麻醉醫(yī)學(xué)知識培訓(xùn)培訓(xùn)課件
- 人教版四年級上冊數(shù)學(xué) 第五單元《平行四邊形和梯形》單元專項訓(xùn)練 作圖題(含答案)
- 物業(yè)品質(zhì)督導(dǎo)述職報告
- 2024年山東濟南軌道交通集團有限公司招聘筆試參考題庫含答案解析
- 療愈行業(yè)現(xiàn)狀分析
- 北京海淀區(qū)2023-2024學(xué)年六年級上學(xué)期期末數(shù)學(xué)數(shù)學(xué)試卷
- 2023年安全總監(jiān)年終工作總結(jié)
評論
0/150
提交評論