C語言-ch08-6-指針數(shù)組與多重指針動態(tài)內(nèi)存分配_第1頁
C語言-ch08-6-指針數(shù)組與多重指針動態(tài)內(nèi)存分配_第2頁
C語言-ch08-6-指針數(shù)組與多重指針動態(tài)內(nèi)存分配_第3頁
C語言-ch08-6-指針數(shù)組與多重指針動態(tài)內(nèi)存分配_第4頁
C語言-ch08-6-指針數(shù)組與多重指針動態(tài)內(nèi)存分配_第5頁
已閱讀5頁,還剩23頁未讀, 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

C語言_ch08_6_指針數(shù)組與多重指針動態(tài)內(nèi)存分配第一頁,共38頁。指針數(shù)組指針數(shù)組

指針組成的數(shù)組例如:int*p[4]由于[]比*優(yōu)先級高,因此p首先與[]結(jié)合,即p是數(shù)組,4個元素分別為p[0]、p[1]、p[2]、p[3]。數(shù)組每個元素的類型是int*,即去掉標識符和[]后的部分。2023/4/152第二頁,共38頁。指針數(shù)組舉例例如,圖書館有若干本書(圖a),

要求對這些書目進行排序和查詢。表示多個字符串的兩種數(shù)據(jù)結(jié)構(gòu)二維字符數(shù)組,圖bcharnames[5][150];字符指針數(shù)組,圖cchar*names[5];2023/4/153第三頁,共38頁。#include<stdio.h>intmain(){inti;char*arr[4]={"C","C++","Java","VBA"};for(i=0;i<4;i++)printf("AddressofString%d:%u\n",i+1,arr[i]);return0;}VBA\0Java\0C++\0C\003C04304204104003F03E03D04404B04A04904804704604504F04E04D04C第四頁,共38頁。0x0042204C0x004220480x004220400x0042203Carrchar*arr[4]={"C","C++","Java","VBA"};C\0C++\0VBA\0Java\02023/4/155第五頁,共38頁。例8.27將多個字符串按字母順序(由小到大)輸出。#include<stdio.h>#include<string.h>voidsort(char*names[],intn);voidprint(char*names[],intn);intmain(){

char*names[]={

"Followme", "BASIC", "GreatWall", "FORTRAN", "ComputerDesign" };

intn=sizeof(names)/sizeof(names[0]);sort(names,n);print(names,n); }2023/4/156第六頁,共38頁。\0\0\0\0\0第七頁,共38頁。voidsort(char*names[],intn)//選擇法排序{

char*temp;

inti,j,k;

for(i=0;i<n-1;i++){k=i;

for(j=i+1;j<n;j++)

//k為當前排序子表最小串的下標{

if(strcmp(names[k],names[j])>0)

k=j;}

if(k!=i){temp=names[i];names[i]=names[k];names[k]=temp;}}}2023/4/158第八頁,共38頁。voidprint(char*names[],intn){

inti;

for(i=0;i<n;i++)printf("%s\n",names[i]);}

運行結(jié)果為:

BASICComputerDesignFORTRANFollowmeGreatWall2023/4/159第九頁,共38頁。8.7.2指向指針的指針指向指針變量的指針變量,簡稱為指向指針的指針。2023/4/1510第十頁,共38頁。指向指針的指針的定義char**p;*運算符的結(jié)合性是從右到左,因此**p相當于*(*p)(*p)前面部分是char*,表明p是指向char*(即一個字符指針變量)的指針變量。指向指針的指針常用在二維數(shù)組中2023/4/1511第十一頁,共38頁。*p就是p所指向的那個指針變量,例p=name+2;printf("%x\n",*p);printf("%s\n",*p);2023/4/1512第十二頁,共38頁。例8.28使用指向指針的指針輸出各字符串。intmain(){

char*name[]={"Followme","BASIC","GreatWall","FORTRAN","ComputerDesign"};

char**p;

inti;

for(i=0;i<5;i++){p=name+i;printf("%s\n",*p);}}2023/4/1513第十三頁,共38頁。例8.29一個指針數(shù)組的元素指向整型數(shù)據(jù)的簡單例子intmain(){

inta[5]={1,3,5,7,9};

int*num[5]={&a[0],&a[1],&a[2],&a[3],&a[4]};

int**p,i;p=num;

for(i=0;i<5;i++){ printf("%d\t",**p); p++; }}運行結(jié)果為:135792023/4/1514第十四頁,共38頁。圖8.39*pnum[2],是a[2]的地址**p即*num[2],也就是a[2]的值52023/4/1515第十五頁,共38頁。8.7.3指針數(shù)組作main函數(shù)的形參在cmd命令行,可通過輸入可執(zhí)行文件名來執(zhí)行。常見dos命令舉例dircdtypeipconfigping…2023/4/1516第十六頁,共38頁。main()函數(shù)的形參intmain(intargc,char*argv[])argc:命令行參數(shù)個數(shù),包括命令字(可執(zhí)行文件名)

argv:是一個指針數(shù)組,用來存放命令行中各個參數(shù)和命令字的字符串,并且規(guī)定:

argv[0]存放命令字

argv[1]存放命令行中第一個參數(shù)

argv[2]存放命令行中第二個參數(shù)

……形參不一定命名為argc和argv2023/4/1517第十七頁,共38頁。//輸出第2到最后一個參數(shù)字符串intmain(intargc,char*argv[]){

while(argc>1) { ++argv;//程序名被跳過 printf("%s\n",*argv); --argc; }

return0;}3argcargv“mainpara”“a.txt”“b.txt”2023/4/1518第十八頁,共38頁。上面程序可以改寫為intmain(intargc,char*argv[]){

while(argc-->1) printf("%s\n",*++argv);

return0;}2023/4/1519第十九頁,共38頁。為什么使用動態(tài)內(nèi)存分配數(shù)組靜態(tài)數(shù)組inta[10];動態(tài)數(shù)組數(shù)組長度動態(tài)指定2023/4/1520第二十頁,共38頁。動態(tài)分配內(nèi)存在<stdlib.h>和<malloc.h>中均定義了下面的函數(shù)void*malloc(size_tsize);size_t是在<stddef.h>中定義的數(shù)據(jù)類型,就是一個unsigned

int向系統(tǒng)申請大小為size的內(nèi)存塊,把指向首地址的指針返回。如果申請不成功(如空間不足),返回NULL如malloc(100);voidfree(void*block);釋放由malloc()申請的內(nèi)存塊。block是指向此塊的指針2023/4/1521第二十一頁,共38頁。int*pi,i;...pi=(int*)malloc(100*sizeof(int));//intpi[100];if(pi==NULL){printf("Outofmemory!\n");exit(1);}...for(i=0;i<100;++i){ pi[i]=0;}...free(pi);pi=NULL;22第二十二頁,共38頁。例8.30建立動態(tài)數(shù)組,輸入n(n由用戶輸入)個學(xué)生的成績,另外用一個函數(shù)輸出不合格的成績。#include<stdio.h>#include<malloc.h>//<stdlib.h>voidprintfailinggrade(int*,int);voidprintfailinggrade(int*p,intn){inti;printf("\nThefailinggrade:");for(i=0;i<n;i++){if(p[i]<60)printf("%d",p[i]);}printf("\n");}23第二十三頁,共38頁。intmain(){

int*pscore,i,n;printf("請輸入學(xué)生人數(shù):");scanf("%d",&n);pscore=(int*)malloc(n*sizeof(int));

if(NULL==pscore) { printf(“Error:Outofmemory!\n"); exit(1); }printf("請輸入%d個成績,用空格隔開:",n);

for(i=0;i<n;i++)scanf("%d",pscore+i);printfailinggrade(pscore,n);free(pscore);pscore=NULL;

return0;}24第二十四頁,共38頁。防止內(nèi)存泄露之道在需要的時候才malloc,并盡量減少malloc的次數(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)鍵要靠程序員的細心與責任感2023/4/1525第二十五頁,共38頁。8.8.3void指針類型void*則為"無類型指針",可以指向任何類型的數(shù)據(jù)。float*p1;

int*p2;

p1=p2;

其中p1=p2語句會編譯出錯,提示"'=':cannotconvertfrom'int*'to'float*'"必須改為:

p1=(float*)p2;2023/4/1526第二十六頁,共38頁。而void*則不同,任何類型的指針都可以直接賦值給它,無需進行強制類型轉(zhuǎn)換:

void*p1;

int*p2;

p1=p2;下面的語句編譯出錯:

void*p1;

int*p2;

p2=p1;

提示"'=':cannotconvertfrom'void*'to'int*'"。2023/4/1527第二十七頁,共38頁。void的使用規(guī)則一:如果函數(shù)沒有返回值,那么應(yīng)聲明為void類型

規(guī)則二:如果函數(shù)無參數(shù),那么應(yīng)聲明其參數(shù)為void規(guī)則三:小心使用void指針類型規(guī)則四:如果函數(shù)的參數(shù)可以是任意類型指針,那么應(yīng)聲明其參數(shù)為void*2023/4/1528第二十八頁,共38頁。關(guān)于野指針(懸掛指針)懸掛指針:既不為空,也沒有被設(shè)置為與另一個對象有鏈接關(guān)系的指針。野指針是非常危險的,所以要"杜絕"野指針。參見《高質(zhì)量C++/C編程指南》--第7章內(nèi)存管理(2)

2023/4/1529第二十九頁,共38頁。"野指針"的成因主要有兩種:(1)指針變量沒有被初始化。未被初始化的指針變量的缺省值是隨機的。所以,指針變量在定義的同時應(yīng)當被初始化,要么將指針設(shè)置為NULL,要么讓它指向合法的內(nèi)存。例如

char*p=NULL; char*str=(char*)malloc(100);(2)指針p被free或者delete之后,沒有置為NULL,讓人誤以為p是個合法的指針。2023/4/1530第三十頁,共38頁。(3)指針操作超越了變量的作用范圍。這種情況讓人防不勝防,示例程序如下:classA{ public: voidFunc(void){cout<<"FuncofclassA"<<endl;}};voidTest(void){

A*p; { Aa; p=&a; //注意a的生命期

} p->Func(); //p是"野指針"}函數(shù)Test在執(zhí)行語句p->Func()時,對象a已經(jīng)消失,而p是指向a的,所以p就成了"野指針"。但奇怪的是我運行這個程序時居然沒有出錯,這可能與編譯器有關(guān)。2023/4/1531第三十一頁,共38頁。與指針相關(guān)的編程規(guī)則減少出錯的根本是徹底理解指針。與指針相關(guān)的編程規(guī)則

1)

未使用的指針初始化為NULL。

2)

在給指針分配空間前、分配后均應(yīng)作判斷。

3)

指針所指向的內(nèi)容刪除后也要清除指針本身。2023/4/1532第三十二頁,共38頁。遵循這些規(guī)則可以有效地減少指針出錯,我們來看下面的例子:

#include<stdio.h>#include<stdlib.h>intmain(void){

char*str=(char*)malloc(100);strcpy(str,"hello");free(str);

if(str!=NULL){ strcpy(str,"world"); printf(str);}}

請問運行Test函數(shù)可能會有什么樣的結(jié)果?33第三十三頁,共38頁。篡改動態(tài)內(nèi)存區(qū)的內(nèi)容,后果難以預(yù)料,非常危險。因為free(str);之后,str成為野指針,if(str!=NULL)語句不起作用。如果我們牢記規(guī)則3

溫馨提示

  • 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. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論