第09章 指針-清華大學C語言_第1頁
第09章 指針-清華大學C語言_第2頁
第09章 指針-清華大學C語言_第3頁
第09章 指針-清華大學C語言_第4頁
第09章 指針-清華大學C語言_第5頁
已閱讀5頁,還剩89頁未讀, 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

第9章指針制作人:王敬華第9章:指針

學習的意義

語言程序設計教程第二版

第九章指針C

指針是C語言中廣泛使用的一種數(shù)據(jù)類型。

運用指針編程是C語言最主要的風格之一。C程序設計中使用指針可以:

①使程序簡潔、緊湊、高效

②有效地表示復雜的數(shù)據(jù)結構

③動態(tài)分配內(nèi)存

④得到多于一個的函數(shù)返回值

⑤能象匯編語言一樣處理內(nèi)存地址,從而編出精練而高效的程序

學習指針是學習C語言中最重要的一環(huán),

能否正確理解和使用指針是我們是否掌握C語言的一個標志,可以說不懂C語言中的指針就不懂什么是C語言。學習目標

理解指針的概念掌握指針變量的定義與引用方法;掌握指針與數(shù)組、字符串之間的聯(lián)系;掌握動態(tài)內(nèi)存分配和釋放的方法;掌握帶指針型參數(shù)和返回指針的函數(shù)的定義方法;掌握函數(shù)指針的用法;

語言程序設計教程第二版

第九章指針C學習內(nèi)容

指針與指針變量的概念指針變量的定義和引用指針和地址運算指針與數(shù)組數(shù)組的指針和指向數(shù)組的指針變量指向多維數(shù)組的指針____數(shù)組指針元素為指針的數(shù)組____指針數(shù)組指針與字符串指針與動態(tài)內(nèi)存分配多級指針指針與數(shù)組作為函數(shù)的參數(shù)指針作為函數(shù)的返回值____指針函數(shù)指向函數(shù)的指針____函數(shù)指針帶參數(shù)的main函數(shù)本章小結

語言程序設計教程第二版

第九章指針C…...內(nèi)存2000200120022005020032004…...…...…...9.1指針與指針變量的概念1、內(nèi)存地址──內(nèi)存中存儲單元的編號101102201202301302401402501502601602教學樓教室號碼存儲地址教室存儲單元教室有容量存儲單元有大小(字節(jié)單元、字單元)50存儲數(shù)據(jù)注意:內(nèi)存單元的地址與內(nèi)存單元中的數(shù)據(jù)是兩個完全不同的概念。語言程序設計教程第二版

第九章指針C內(nèi)存…...…...0200020012002200520032004…...…...2、變量地址──系統(tǒng)分配給變量的內(nèi)存單元的起始地址程序中:inti;

floatk;

內(nèi)存中每個字節(jié)有一個編號-----地址ik

編譯或函數(shù)調(diào)用時為其分配內(nèi)存單元變量是對程序中數(shù)據(jù)存儲空間的抽象i的地址k的地址注意:在TC或BC下,系統(tǒng)將給變量i分配2字節(jié)的單元,而VC下將是4字節(jié)的單元!語言程序設計教程第二版

第九章指針C整型變量i變量i_pointer…...…...1020002004200620052001200220033、指針與指針變量指針:一個變量的地址指針變量:專門存放變量地址的變量2000指針變量整型變量i的內(nèi)容指針變量i_pointer的內(nèi)容(是地址)變量的地址指針指針變量變量變量地址(指針)變量值指向地址存入指針變量語言程序設計教程第二版

第九章指針C4、&與*運算符含義含義:取變量的地址單目運算符結合性:自右向左含義:

取指針所指向變量的內(nèi)容單目運算符結合性:自右向左兩者關系:互為逆運算理解200010i_pointer*i_pointer&i_pointerii_pointer&i&(*i_pointer)i*i_pointer*(&i)i_pointer

=

&i

=

&(*i_pointer)i

=

*i_pointer

=

*(&i)…...…...2000200420062005整型變量i10變量i_pointer2001200220032000指針變量i_pointer-----指針變量,它的內(nèi)容是地址量*i_pointer----指針的目標變量,它的內(nèi)容是數(shù)據(jù)&i_pointer---指針變量占用內(nèi)存的地址語言程序設計教程第二版

第九章指針C直接訪問:按變量名來存取變量值間接訪問:通過存放變量地址的變量去訪問變量例

i=3;-----直接訪問指針變量…...…...2000200420062005整型變量i10變量i_pointer20012002200320003例

*i_pointer=20;-----間接訪問209.2指針變量的定義和引用

1、變量值的存取方法語言程序設計教程第二版

第九章指針C指針變量…...…...2000200420062005整型變量i10變量i_pointer2001200220032000整型變量k10例

k=i;k=*i_pointer;--直接訪問--間接訪問語言程序設計教程第二版

第九章指針C2、指針變量與其所指向的變量之間的關系3變量i2000i_pointer*i_pointeri*i_pointer&ii_pointeri=3;*i_pointer=3;3、指針變量的定義一般形式:[存儲類型]數(shù)據(jù)類型符*變量名;合法標識符表示定義指針變量不是‘*’運算符指針的目標變量的數(shù)據(jù)類型指針變量本身的存儲類型注意:

int*p1,*p2;與int*p1,p2;

指針變量名是p1,p2,不是*p1,*p2

指針變量只能指向定義時所規(guī)定類型的變量

指針變量定義后,變量值不確定,應用前必須先賦值例

int

*p1,*p2;float*q;staticchar*name;語言程序設計教程第二版

第九章指針C例

inti;int*p=&i;例int*p=&i;

inti;例

voidmain(){inti;staticint*p=&i;..............}()標準C下不能用auto變量的地址去初始化static型指針(但在C++程序中可以)

4、指針變量的賦值初始化賦值[存儲類型]

數(shù)據(jù)類型*指針名=初始地址值;賦給指針變量,不是賦給目標變量變量必須已說明過類型應一致例

inti;int*p=&i;int*q=p;用已初始化指針變量作初值語言程序設計教程第二版

第九章指針C例

inta;int*p;p=&a;賦值語句賦值例

inta=20;int*p,*q;p=&a;

q=p;整型變量a指針變量p指針變量q……...2000…...…...2020002000語言程序設計教程第二版

第九章指針C例

int*p=&a;inta;指針變量賦值的幾種錯誤方法:

變量a的定義在后,對a的引用超出了a的作用域例

inta;int*pi=&a;char*pc=&a;pc不能指向非字符型變量例

inta;int*p;*p=&a;賦值語句中,被賦值的指針變量p的前面不能再加“*”說明符例

int*p;p=2000;不允許直接把一個數(shù)賦值給指針變量例

inta;staticint*p=&a;不能用auto變量的地址去初始化static型指針注意:一個指針變量只能指向同類型的變量如果給指針賦值時,=號右邊的指針類型與左邊的指針類型不同,則需要進行類型強制轉換。

inta;

int*pi;char*pc;pi=&a;//pi指向apc=(char*)pi;//pc也指向了a,即pi和pc的值都是a的地址語言程序設計教程第二版

第九章指針C5、零指針與空類型指針零指針:(空指針)

定義:指針變量值為零表示:

int*p=0;

p指向地址為0的單元,系統(tǒng)保證該單元不作它用表示指針變量值沒有意義#defineNULL0int*p=NULL:

p=NULL與未對p賦值不同

用途:

避免指針變量的非法引用在程序中常作為狀態(tài)比較

例int*p;......while(p!=NULL){...…}void*類型指針表示:void*p;

使用時要進行強制類型轉換表示不指定p是指向哪一種類型數(shù)據(jù)的指針變量例

char*p1;void*p2;p1=(char*)p2;p2=(void*)p1;語言程序設計教程第二版

第九章指針C6、引用指針變量inta;int*p=&a;//p指向a*p=10;//相當于a=10;格式:

*指針變量inta,*p;p=&a;*p=10;a++;printf("a=%d,*p=%d",a,*p);輸出結果:a=11,*p=11可寫成(*p)++,而不是*p++

注意:程序在利用指針間接引用內(nèi)存單元時,將按照指針變量定義時所指向的數(shù)據(jù)類型來解釋引用的內(nèi)存單元。語言程序設計教程第二版

第九章指針C【例1】不同類型的指針操作同一內(nèi)存變量

#include<stdio.h>voidmain(){unsignedshorta;unsignedshort*pi=&a;char*pc=(char*)&a;*pi=0XF0F0;*pc=0;

printf("a=%X",a);}……...2000…...…...整型變量a指針變量pi2000pi可操作單元指針變量pc2000pc可操作單元F0F000輸出結果:a=F000語言程序設計教程第二版

第九章指針C【例2】輸入兩個數(shù),并使其從大到小輸出#include<stdio.h>voidmain(){int*p1,*p2,*p,a,b;

scanf("%d,%d",&a,&b);p1=&a;p2=&b;if(a<b){p=p1;p1=p2;p2=p;}

printf("a=%d,b=%d\n",a,b);

printf("max=%d,min=%d\n",*p1,*p2);}運行結果:a=5,b=9max=9,min=5…...…...指針變量p1指針變量p20002008200220042006指針變量p2整型變量b整型變量a5200692008200620082006重點強調(diào):指針變量必須先定義,后賦值,最后才能使用!沒有賦值的指針變量是沒有任何意義的,也絕對是不允許使用的。指針變量只能指向定義時所規(guī)定類型的變量。指針變量也是變量,在內(nèi)存中也要占用一定的內(nèi)存單元,但所有類型的指針變量都占用同樣大小的內(nèi)存單元,其具體大小取決于所使用的編譯環(huán)境,如在BC3.1和VC6.0下為4個字節(jié),在TC2.0下為2個字節(jié)。語言程序設計教程第二版

第九章指針C1、指針變量的加、減運算9.3指針和地址運算

指針可以參與加法和減法運算,但其加、減的含義絕對不同于一般數(shù)值的加減運算。如果指針p是這樣定義的:ptype*p;,并且p當前的值是ADDR,那么:p±n的值=ADDR±n*sizeof(ptype)int*pi;char*pc;long*pl;pi=(int*)1000;pc=(char*)1000;pl=(long*)1000;pi++;//pi的值將是1002(假設int型占2byte)pi-=2;//pi的值將是998pc++;//pc的值將是1001pc-=2;//pc的值將是999pl++;//pl的值將是1004pl-=2;//pi的值將是996注意:兩個指針相加沒有任何意義,但兩個指針相減則有一定的意義,可表示兩指針之間所相差的內(nèi)存單元數(shù)或元素的個數(shù),在后面的學習中就會體會到。

語言程序設計教程第二版

第九章指針C2、指針變量的關系運算若p1和p2指向同一數(shù)組,則

p1<p2表示p1指的元素在前

p1>p2表示p1指的元素在后

p1==p2表示p1與p2指向同一元素若p1與p2不指向同一數(shù)組,比較無意義p==NULL或p!=NULL語言程序設計教程第二版

第九章指針C1、數(shù)組的指針9.4指針與數(shù)組

數(shù)組的指針其實就是數(shù)組在內(nèi)存中的起始地址。而數(shù)組在內(nèi)存中的起始地址就是數(shù)組變量名,也就是數(shù)組第一個元素在內(nèi)存中的地址。a2000200220042018…...…...a[0]a[1]a[2]a[9]aa+1a+2a+9……例:shortinta[10];inta[10];intk;for(k=0;k<10;k++)

a[k]=k;

//利用數(shù)組下標inta[10];intk;for(k=0;k<10;k++)*(a+k)=k;//利用數(shù)組的指針注意:a+k

&a[k]*(a+k)a[k]語言程序設計教程第二版

第九章指針C2、指向數(shù)組的指針變量9.4指針與數(shù)組

如果將數(shù)組的起始地址賦給某個指針變量,那么該指針變量就是指向數(shù)組的指針變量。例:shortinta[10],p=a;p2000200220042018…...aa+1a+2a+9………...a[0]a[1]a[2]a[9]2000pp+1p+2p+9……*a*(a+1)*(a+2)*(a+9)……*p*(p+1)*(p+2)*(p+9)……p[0]p[1]p[2]p[9]……地址元素

注意:p+1指向數(shù)組的下一個元素,而不是簡單地使指針變量p的值+1。其實際變化為p+1*size(size為一個元素占用的字節(jié)數(shù))。例如,假設指針變量p的當前值為2000,則p+1為2000+1*2=2002,而不是2001。語言程序設計教程第二版

第九章指針Ccharstr[10];intk;for(k=0;k<10;k++)

str[k]='A'+k;

//也可寫成*(str+k)='A'+kcharstr[10];intk;char*p;p=str;for(k=0;k<10;k++)

p[k]='A'+k;

//也可寫成*(p+k)='A'+k

charstr[10];intk;char*p;p=str;for(k=0;k<10;k++)

*p++='A'+k;

//相當于*p='A'+k;p++;

下面是對數(shù)組元素賦值的幾種方法,它們從功能上是等價的

執(zhí)行完后,p仍然指向數(shù)組str的首地址執(zhí)行完后,p指向數(shù)組元素str[9]的下一內(nèi)存單元

注意:數(shù)組名是地址常量,切不可對其賦值,也不可做++或--運算。例如:inta[10];如果在程序中出現(xiàn)a++或a--則是錯誤的。語言程序設計教程第二版

第九章指針Ca[0]a[1]a[2]a[3]a[4]

【例】數(shù)組元素的引用方法voidmain(){

inta[5],*pa,i;for(i=0;i<5;i++)

a[i]=i+1;pa=a;for(i=0;i<5;i++)

printf("*(pa+%d):%d\n",i,*(pa+i));for(i=0;i<5;i++)

printf("*(a+%d):%d\n",i,*(a+i));for(i=0;i<5;i++)

printf("pa[%d]:%d\n",i,pa[i]);for(i=0;i<5;i++)

printf("a[%d]:%d\n",i,a[i]);}12345pa語言程序設計教程第二版

第九章指針C例:

inta[]={1,2,3,4,5,6,7,8,9,10},*p=a,i;

數(shù)組元素地址的正確表示:

(A)&(a+1)(B)a++(C)&p(D)&p[i]數(shù)組名是地址常量p++,p--()a++,a--()a+1,*(a+2)()例:注意指針變量的運算voidmain(){

inta[]={5,8,7,6,2,7,3};

inty,*p=&a[1];

y=(*--p)++;

printf(“%d”,y);

printf(“%d”,a[0]);}58762730123456app6輸出結果:56語言程序設計教程第二版

第九章指針Cvoidmain(){

inti,*p,a[7];p=a;for(i=0;i<7;i++)

scanf("%d",p++);

printf("\n");for(i=0;i<7;i++,p++)

printf("%d",*p);}例

注意指針的當前值p=a;pp58762730123456apppppp指針變量可以指到數(shù)組后的內(nèi)存單元語言程序設計教程第二版

第九章指針C#include<stdio.h>voidmain(){shortinta[2][3]={{1,2,3},{4,5,6}};shortinti,j,*p;

p=&a[0][0];

for(i=0;i<2;i++){for(j=0;j<3;j++)

printf("a[%d][%d]=%d",i,j,*(p+i*3+j));

printf("\n");}}3、指向多維數(shù)組的指針____數(shù)組指針利用指針變量不僅可以引用一維數(shù)組,而且也可以引用多維數(shù)組?!纠坷靡话阒羔樧兞繉ΧS數(shù)組的引用。200020022004200620082010a[0]a[1]2000a[0][0]1a[0][1]2a[0][2]3a[1][0]4a[1][1]5a[1][2]6pp+1p+2p+3p+4p+5a[0]a[0]+1a[0]+2a[0]+3a[0]+4a[0]+5a[1]a[1]+1a[1]+2地址指針P所占內(nèi)存單a[0]a[1]

當指針p指向這個二維數(shù)組時,其實p就相當于一個一維數(shù)組,因此訪問二維數(shù)組中的元素可分別用p[0]…p[5]或*(p+0)…*(p+5)來表示

注意:假設有一個m行n列的二維數(shù)組a:

a[i](i在0到m-1之間)為第i+1行的首地址,是一個地址常量。如上例中的a[0]表示第一行的首地址,當然也是整個二維數(shù)組元素所占內(nèi)存單元的首地址,a[1]表示第二行的首地址。當二維數(shù)組的首地址賦給指針變量p以后,則訪問某個元素a[i][j]可用以下幾種方式來代替:*(p+i*n+j)、p[i*n+j]、*(a[0]+i*n+j)。二維數(shù)組名a不可賦值給一般指針變量p,只能賦值給指向二維數(shù)組的指針變量。p=a;是非法的。語言程序設計教程第二版

第九章指針C3、指向多維數(shù)組的指針____數(shù)組指針語言程序設計教程第二版

第九章指針C(1)二維數(shù)組的行地址與列地址a[0]a[1]a[2]a+0&a[0]a+1&a[1]a+2&a[2]a[0]+0a[0]+1a[0]+2a[0]+3一維數(shù)組a[0]a[0][0]a[0][1]a[0][2]a[0][3]a[1]+0a[1]+1a[1]+2a[1]+3一維數(shù)組a[1]a[1][0]a[1][1]a[1][2]a[1][3]a[2]+0a[2]+1a[2]+2a[2]+3一維數(shù)組a[2]a[2][0]a[2][1]a[2][2]a[2][3]列地址列地址列地址行地址一維數(shù)組ainta[3][4];3、指向多維數(shù)組的指針____數(shù)組指針語言程序設計教程第二版

第九章指針C

如果將二維數(shù)組名a看成一個行地址(第0行的地址),則a+i代表二維數(shù)組a的第i行的地址,a[i]可看成一個列地址,即第i行第0列的地址。行地址a每次加1,表示指向下一行,而列地址a[i]每次加1,表示指向下一列。*(*(a+i)+j)a:第0行的地址a+i:第i行的地址*(a+i):即a[i],第i行第0列的地址*(a+i)+j:即&a[i][j],第i行第j列的地址*(*(a+i)+j):即a[i][j],第i行第j列的元素對于二維數(shù)組:(1)a是數(shù)組名,包含三個元素

a[0],a[1],a[2](2)每個元素a[i]

又是一個一維數(shù)組,包含4個元素aa+1a+2*(*(a+0)+1)*(a[0]+1)inta[3][4];a[0]a[1]a[2]200020082016200020022008201020162018a[0][0]a[0][1]a[1][0]a[1][1]a[2][0]a[2][1]a[0][2]a[0][3]a[1][2]a[1][3]a[2][2]a[2][3]基類型行指針與列指針a[0]+1a[1]+1a[2]+1*(a+0)+1*(a+1)+1*(a+2)+13、指向多維數(shù)組的指針____數(shù)組指針二維數(shù)組的理解:語言程序設計教程第二版

第九章指針Ca+i=&a[i]=a[i]=*(a+i)=&a[i][0],

值相等,含義不同a+i

&a[i],表示第i行首地址,指向行a[i]*(a+i)&a[i][0],表示第i行第0列元素地址,指向列inta[3][4];200020022008201020162018a[0][0]a[0][1]a[1][0]a[1][1]a[2][0]a[2][1]a[0][2]a[0][3]a[1][2]a[1][3]a[2][2]a[2][3]a[0]a[1]a[2]200020162008aa+1a+2二維數(shù)組的理解:對二維數(shù)組inta[3][4],有:a-----二維數(shù)組的首地址,即第0行的首地址a+i-----第i行的首地址a[i]*(a+i)------第i行第0列的元素地址a[i]+j

*(a+i)+j-----第i行第j列的元素地址*(a[i]+j)*(*(a+i)+j)a[i][j]語言程序設計教程第二版

第九章指針Cinta[3][4];a[0][0]a[0][1]a[1][0]a[1][1]a[2][0]a[2][1]a[0][2]a[0][3]a[1][2]a[1][3]a[2][2]a[2][3]二維數(shù)組元素表示形式:(1)a[1][2](2)*(a[1]+2)(3)*(*(a+1)+2)(4)*(&a[0][0]+1*4+2)地址表示:(1)a+1

(2)&a[1][0](3)a[1](4)*(a+1)(5)(int*)(a+1)行指針列指針地址表示:(1)&a[1][2](2)a[1]+2(3)*(a+1)+2(4)&a[0][0]+1*4+2二維數(shù)組的理解:語言程序設計教程第二版

第九章指針C表示形式含義地址a二維數(shù)組名,數(shù)組首地址a[0],*(a+0),*a第0行第0列元素地址a+1第1行首地址a[1],*(a+1)第1行第0列元素地址a[1]+2,*(a+1)+2,&a[1][2]第1行第2列元素地址*(a[1]+2),*(*(a+1)+2),a[1][2]第1行第2列元素值2000200020082008201213二維數(shù)組的理解:語言程序設計教程第二版

第九章指針C3、指向多維數(shù)組的指針____數(shù)組指針指向二維數(shù)組的行指針變量的定義格式:

數(shù)據(jù)類型符(*指針變量名)[常量表達式];二維數(shù)組第二維的大小

括號不能省例:inta[2][3];

int(*p)[3];()

int*p[3];()

int(*p)[2];()語言程序設計教程第二版

第九章指針C(2)通過二維數(shù)組的行指針來訪問二維數(shù)組【例】利用指向二維數(shù)組的行指針變量對二維數(shù)組的引用。#include<stdio.h>voidmain(){shortinta[2][3]={{1,2,3},{4,5,6}};

shortint(*p)[3];shortinti,j;p=a;for(i=0;i<2;i++){for(j=0;j<3;j++)

printf("a[%d][%d]=%d",i,j,p[i][j]);

printf("\n");}p++;

for(j=0;j<3;j++)

printf("%d",p[0][j]);}200020022004200620082010a[0]a[1]p2000a[0][0]1a[0][1]2a[0][2]3a[1][0]4a[1][1]5a[1][2]6a[0](2000)a[1](2006)看成一維數(shù)組p++后p的指向p=a運行結果:a[0][0]=1a[0][1]=2a[0][2]=3a[1][0]=4a[1][1]=5a[1][2]=6456*(*p+i*3+j)或(*p+i*3)[j]注意:對指向二維數(shù)組的行指針變量進行賦值一般形式為:

(1)二維數(shù)組名+整型常數(shù)n,如:p=a+1;或

(2)&二維數(shù)組名[整型常量n],如:p=&a[1]。不可用數(shù)組單元地址對其賦值。如:p=a[0];或p=&a[0][0]都是錯誤的。語言程序設計教程第二版

第九章指針C4、元素為指針的數(shù)組____指針數(shù)組

當某個數(shù)組單元都是指針型數(shù)據(jù)時,這個數(shù)組被稱為指針數(shù)組。其定義的一般格式為:數(shù)據(jù)類型符*變量名[常量表達式];例:

charc[3]={'a','b','c'};

char*p[3];p[0]=&c[0];p[1]=&c[1];p[2]=&c[2];指針數(shù)組p200020012002數(shù)組cc[0]

'a'c[1]

'b'c[2]

'c'p[0]2000p[1]2001p[2]2002語言程序設計教程第二版

第九章指針C4、指針數(shù)組與數(shù)組指針的比較int*p[3];①表明p是數(shù)組變量②表明p中的單元都是指針③表明p中的單元都是int型的指針指針數(shù)組int(*p)[3];①表明p是指針變量②表明p指向大小為3的數(shù)組③表明p指向的數(shù)組是int型數(shù)組數(shù)組指針指針數(shù)組二維數(shù)組指針變量定義int*p[20];int(*p)[20];變量性質p是數(shù)組名,不是指針變量,不可對p賦值P是指針變量,不是數(shù)組名,可對p賦值語言程序設計教程第二版

第九章指針C【例】利用指針數(shù)組對鍵盤輸入的5個整數(shù)進行從小到大排序。#include<stdio.h>voidmain(){

inti,j,t;

inta,b,c,d,e;

//將a,b,c,d,e的內(nèi)存地址分別賦給p[0]...p[4]

int*p[5]={&a,&b,&c,&d,&e};//對a,b,c,d,e賦值

scanf("%d,%d,%d,%d,%d",p[0],p[1],p[2],p[3],p[4]);for(i=0;i<4;i++)//利用冒泡法排序

for(j=i+1;j<5;j++)if(*p[i]>*p[j])//交換p[i]、p[j]所指向的變量值

{t=*p[i];*p[i]=*p[j];*p[j]=t;}for(i=0;i<5;i++)//顯示排序后的結果

printf("%d",*p[i]);}運行結果(假設輸入:38764):34678語言程序設計教程第二版

第九章指針C20002010202020302040變量所占內(nèi)存單元(不一定連續(xù))abcdep[0]2000p[1]2010p[2]2020p[3]2030p[4]2040指針數(shù)組p(占用連續(xù)的存儲單元)注意:該方法是將a,b,c,d,e所對應的內(nèi)存單元的值進行交換,而指針數(shù)組并無變化。問:如果a,b,c,d,e的值不變,能否進行排序?語言程序設計教程第二版

第九章指針C9.5指針與字符串1、字符串表示形式用字符數(shù)組實現(xiàn)例:voidmain(){charstring[]=“IloveChina!”;

printf(“%s\n”,string);

printf(“%s\n”,string+7);}IloveChistring[0]string[1]string[2]string[3]string[4]string[5]string[6]string[7]string[8]string[9]stringstring[10]string[11]string[12]string[13]n!a\0運行結果:IloveChina!China!語言程序設計教程第二版

第九章指針C用字符指針實現(xiàn)例:

voidmain(){

char*string=“IloveChina!”;

printf(“%s\n”,string);

string+=7;while(*string){

putchar(string[0]);string++;}}IloveChistringn!a\0字符指針初始化:把字符串首地址賦給stringchar*string;string=“IloveChina!”;string*string!=0運行結果:IloveChina!China!整體引用逐個字符引用語言程序設計教程第二版

第九章指針C2、字符指針變量與字符數(shù)組char*cp;與

charstr[20];

str由若干元素組成,每個元素放一個字符;而cp中存放字符串首地址

charstr[20];str=“IloveChina!”;()char*cp;cp=“IloveChina!”;()

str是地址常量;cp是地址變量

cp接受鍵入字符串時,必須先開辟存儲空間例

charstr[10];

scanf(“%s”,str);()而

char*cp;

scanf(“%s”,cp);()改為:char*cp,str[10];cp=str;

scanf(“%s”,cp);()語言程序設計教程第二版

第九章指針C3、字符串與數(shù)組關系字符串用一維字符數(shù)組存放字符數(shù)組具有一維數(shù)組的所有特點數(shù)組名是指向數(shù)組首地址的地址常量數(shù)組元素的引用方法可用指針法和下標法數(shù)組名作函數(shù)參數(shù)是地址傳遞等區(qū)別存儲格式:字符串結束標志賦值方式與初始化輸入輸出方式:%s%ccharstr[]={“Hello!”};()charstr[]=“Hello!”;()charstr[]={‘H’,‘e’,‘l’,‘l’,‘o’,‘!’};()char*cp=“Hello”;()inta[]={1,2,3,4,5};()int*p={1,2,3,4,5};()charstr[10],*cp;inta[10],*p;str=“Hello”;()cp=“Hello!”;()a={1,2,3,4,5};()p={1,2,3,4,5};()scanf(“%s”,str);printf(“%s”,str);gets(str);puts(str);語言程序設計教程第二版

第九章指針C4、字符指針變量使用注意事項當字符指針指向字符串時,除了可以被賦值之外,與包含字符串的字符數(shù)組沒有什么區(qū)別。charstr[10],*pstr;pstr="12345";//pstr指向"12345"strcpy(str,pstr);//將pstr所指向的字符串復制到數(shù)組str中pstr=str;printf("TheLengthofstris:%d\n",strlen(pstr));//輸出字符串的長度5注意“野指針”操作:如果一個指針沒有指向一個有效內(nèi)存就被引用,則被稱為“野指針”操作或空指針賦值。野指針操作盡管編譯時不會出錯,但很容易引起程序運行時表現(xiàn)異常,甚至導致系統(tǒng)崩潰。char*pstr;charstr[8];scanf("%s",pstr);//野指針操作,pstr沒有指向有效內(nèi)存strcpy(pstr,"hello");//野指針操作pstr=str;//pstr指向數(shù)組str所對應內(nèi)存單元的首地址strcpy(pstr,"0123456789");//不是野指針,但會造成數(shù)組越界

為什么“野指針”操作會給程序運行帶來極大的不確定性,甚至造成系統(tǒng)崩潰呢?語言程序設計教程第二版

第九章指針C系統(tǒng)程序區(qū)0001pstr0001指針pstr所占內(nèi)存char*pstr;pstr=‘a(chǎn)’;隨機值,有可能指向系統(tǒng)程序區(qū)假設首地址為0001此時對pstr指向的內(nèi)存單元賦值極其危險!為什么“野指針”賦值會給程序運行帶來極大的危險?再次提醒:指針變量只有與內(nèi)存建立聯(lián)系以后才可使用,否則將造成程序運行異常,甚至導致系統(tǒng)死機!語言程序設計教程第二版

第九章指針C【例】利用字符指針實現(xiàn)字符串的倒序排列

#include<stdio.h>#include<string.h>voidmain(){charstr[200],ch;char*p,*q;gets(str);//讀取一個字符串

p=str;//p指向字符串的首地址

q=p+strlen(p)-1;//q指向字符串的末地址

while(p<q){//交換p和q各自指向的字符

ch=*p;//將p所指向的字符保存在ch中*p++=*q;//先將q指向的字符賦給p指向的字符單元,p再增1*q--=ch;//先將ch的值賦給q指向的字符單元,q再減1}

printf("%s\n",str);}運行結果:IloveChina!↙!anihC

evolI語言程序設計教程第二版

第九章指針C'I''''L''o''v''e''''C''h''i''n''a''!'0strpq

p=str;q=p+strlen(p)-1交換'!''I'pq交換'a'pq交換'n''L'pq交換'i''o'pq交換'h''v'''pq'C''e'交換pq''End程序執(zhí)行過程演示:語言程序設計教程第二版

第九章指針C字符串指針數(shù)組與字符串二維數(shù)組之間的區(qū)別

charstr[3][10]={"Wuhan","Beijing","Shanghai"};char*pstr[3];pstr[0]=str[0];pstr[1]=str[1];pstr[2]=str[2];pstr[0]pstr[1]pstr[2]'W''u''h''a''n'00000'B''e''i''j''i''n''g'000'S''h''a''n''g''h''a''i'00pstrstr字符串結束標志多余空位補0語言程序設計教程第二版

第九章指針C定義字符指針數(shù)組時直接用字符串對其賦初始值

char*pstr[3]={"Wuhan","Beijing","Shanghai"};pstr[0]pstr[1]pstr[2]'W''u''h''a''n'0'B''e''i''j''i''n''g'0'S''h''a''n''g''h''a''i'0pstrstr字符串結束標志語言程序設計教程第二版

第九章指針C#include<stdio.h>#include<string.h>voidmain(){

inti,j,k;

char*pcity[]={"Wuhan",Beijing","Shanghai","Tianjin","Guangzhou",""};

char*ptemp;for(i=0;strcmp(pcity[i],"")!=0;i++){k=i;for(j=i+1;strcmp(pcity[j],"")!=0;j++)if(strcmp(pcity[k],pcity[j])>0)k=j;if(k!=i){ptemp=pcity[i];pcity[i]=pcity[k];pcity[k]=ptemp;}}【例】利用字符指針數(shù)組對一組城市名進行升序排列。運行結果:BeijingGuangzhouShanghaiTianjin

Wuhan

for(i=0;strcmp(pcity[i],"")!=0;i++)printf("%s",pcity[i]);

printf("\n");}選擇排序語言程序設計教程第二版

第九章指針C9.6指針與動態(tài)內(nèi)存分配1、靜態(tài)內(nèi)存分配

當程序中定義變量或數(shù)組以后,系統(tǒng)就會給變量或數(shù)組按照其數(shù)據(jù)類型及大小來分配相應的內(nèi)存單元,這種內(nèi)存分配方式稱為靜態(tài)內(nèi)存分配。intk;//系統(tǒng)將給變量k分配2個字節(jié)(VC下分配4個字節(jié))的內(nèi)存單元charch[10];//系統(tǒng)將給這個數(shù)組ch分配10個字節(jié)的內(nèi)存塊,首地址就是ch的值靜態(tài)內(nèi)存分配一般是在已知道數(shù)據(jù)量大小的情況下使用

例如,要對10個學生的成績按降序輸出,則可定義一個數(shù)組:intscore[10];

用于存放10個學生的成績,然后再進行排序。

如果事先并不知道學生的具體人數(shù),編寫程序時,人數(shù)由用戶輸入,然后再輸入學生的成績。那有如何如何處理呢?intn;int

score[n];scanf("%d",&n);如何解決?動態(tài)內(nèi)存分配語言程序設計教程第二版

第九章指針C2、動態(tài)內(nèi)存分配

所謂動態(tài)內(nèi)存分配是指在程序運行過程中,根據(jù)程序的實際需要來分配一塊大小合適的連續(xù)的內(nèi)存單元。程序可以動態(tài)分配一個數(shù)組,也可以動態(tài)分配其它類型的數(shù)據(jù)單元。動態(tài)分配的內(nèi)存需要有一個指針變量記錄內(nèi)存的起始地址。

(1)malloc

函數(shù)malloc()用于分配若干個字節(jié)的內(nèi)存空間,返回一個指向該存儲區(qū)地址的指針。其函數(shù)的原型為:void*malloc(unsignedintsize);說明:size這個參數(shù)的含義是分配的內(nèi)存的大?。ㄒ宰止?jié)為單位)。返回值:失敗,則返回值是NULL(空指針)。成功,則返回值是一個指向空類型(void)的指針(即所分配內(nèi)存塊的首地址)。語言程序設計教程第二版

第九章指針C2、動態(tài)內(nèi)存分配

intn,*pscore;scanf("%d",&n);//分配n個連續(xù)的整型單元,首地址賦給pscorepscore=(int*)malloc(n*sizeof(int));//分配內(nèi)存失敗,則給出錯誤信息后退出if(pscore==NULL){

printf("Insufficientmemoryavailable!");exit(0);}……//可對pscore所指向的單元進行其它處理例如:根據(jù)學生人數(shù)來建立數(shù)組的問題可以用動態(tài)內(nèi)存分配來解決,其方法如下:動態(tài)分配的內(nèi)存塊0100pscore0100

共n*sizeof(int)個字節(jié)內(nèi)存單元語言程序設計教程第二版

第九章指針C關于malloc的使用有幾點需強調(diào)一下:malloc前面必須要加上一個指針類型轉換符,如前面的(int*)。因為malloc的返回值是空類型的指針,一般應與右邊的指針變量類型一致。malloc所帶的一個參數(shù)是指需分配的內(nèi)存單元字節(jié)數(shù),盡管可以直接用數(shù)字來表示,但一般寫成如下形式:分配數(shù)量*sizeof(內(nèi)存單元類型符)malloc可能返回NULL,表示分配內(nèi)存失敗,因此一定要檢查分配的內(nèi)存指針是否為空,如果是空指針,則不能引用這個指針,否則會造成系統(tǒng)崩潰。所以在動態(tài)內(nèi)存分配的語句的后面一般緊跟一條if語句以判斷分配是否成功。語言程序設計教程第二版

第九章指針C語言程序設計教程第二版

第九章指針C

(2)calloc

函數(shù)calloc()用于給若干個同一類型的數(shù)據(jù)項分配連續(xù)的存儲空間,其中每個數(shù)據(jù)項的長度單位為字節(jié)。通過調(diào)用函數(shù)calloc()所分配的存儲單元,系統(tǒng)將其自動置初值0。其函數(shù)的原型為:void*calloc(unsignedintnum,unsignedintsize);說明:num表示向系統(tǒng)申請的內(nèi)存空間的數(shù)量,size表示申請的每個內(nèi)存空間的字節(jié)數(shù)。如果分配內(nèi)存失敗,將返回空指針(NULL);如果成功,將返回一個void類型的連續(xù)存儲空間的首地址。intn,*pscore;scanf("%d",&n);//分配n個連續(xù)的整型單元,首地址賦給pscorepscore=(int*)calloc(n,sizeof(int));//分配內(nèi)存失敗,則給出錯誤信息后退出if(pscore==NULL){

printf("Insufficientmemoryavailable!");exit(0);}……//可對pscore所指向的單元進行其它處理語言程序設計教程第二版

第九章指針C

(3)ralloc

函數(shù)realloc()用于改變原來分配的存儲空間的大小。

其函數(shù)的原型為:void*realloc(void*p,unsignedintsize);

功能:將指針p所指向的存儲空間的大小改為size個字節(jié)。

返值:如果分配內(nèi)存失敗,將返回空指針(NULL);如果成功,將返回新分配的存儲空間的首地址,該首地址與原來分配的首地址不一定相同。

函數(shù)realloc()主要應用場合是:當先前通過動態(tài)內(nèi)存分配的存儲空間因實際情況需要進行擴充或縮小時,就可以使用函數(shù)realloc()來解決,其好處是原存儲空間中的數(shù)據(jù)值能保持不變。例如有下列程序段:語言程序設計教程第二版

第九章指針Cchari,*p;p=(char*)malloc(4*sizeof(char));for(i=0;i<4;i++)*(p+i)=i+1;1234p4字節(jié)6字節(jié)1234p=(char*)realloc(p,6*sizeof(char));p3、動態(tài)內(nèi)存釋放計算機中最寶貴的資源就是內(nèi)存。因此需要動態(tài)分配內(nèi)存的程序一定要堅持“好借好還,再借不難”的原則。釋放動態(tài)內(nèi)存的函數(shù)free其原型為:voidfree(void*block);例:free(pscore);

注意:調(diào)用malloc,calloc,realloc和free函數(shù)的源程序中要包含stdlib.h或malloc.h或alloc.h(在TC、BC下)。malloc或calloc或realloc與free一般成對出現(xiàn)!語言程序設計教程第二版

第九章指針C【例】編寫程序先輸入學生人數(shù),然后輸入學生成績,最后輸出學生的平均成績、最高成績和最低成績。

#include<stdio.h>#include<stdlib.h>#include<malloc.h>voidmain(){

intnum,i;

int

maxscore,minscore,sumscore;

int*pscore;floataverscore;

printf("inputthenumberofstudent:");

scanf("%d",&num);if(num<=0)return;

pscore=(int*)malloc(num*sizeof(int));

if(pscore==NULL){

printf("Insufficientmemoryavailable\n");exit(0);}

printf("inputthescoresofstudentsnow:\n");for(i=0;i<num;i++)

scanf("%d",pscore+i);

maxscore=pscore[0];

minscore=pscore[0];

sumscore=pscore[0];for(i=1;i<num;i++){if(pscore[i]>maxscore)

maxscore=pscore[i];if(pscore[i]<minscore)

minscore=pscore[i];

sumscore=sumscore+pscore[i];}

averscore=(float)sumscore/num;

printf("----------------------------------------------\n");

printf("theaveragescoreofthestudentsis%.1f\n",

averscore);

printf("thehighestscoreofthestudentsis%d\n",

maxscore);

printf("thelowestscoreofthestudentsis%d\n",

minscore);

free(pscore);

//釋放動態(tài)分配的內(nèi)存}運行結果:inputthenumberofstudent:4↙inputthescoresofstudentsnow:45768894↙----------------------------------------------theaveragescoreofthestudentsis75.8thehighestscoreofthestudentsis94thelowestscoreofthestudentsis45語言程序設計教程第二版

第九章指針C9.7多級指針定義:指向指針的指針一級指針:指針變量中存放目標變量的地址p1&p2&i3p2(指針變量)i(整型變量)例

int

**p1;

int*p2;

inti=3;p2=&i;p1=&p2;**p1=5;二級指針:指針變量中存放一級指針變量的地址例

int*p;

inti=3;p=&i;*p=5;&i3p(指針變量)i(整型變量)一級指針單級間接尋址二級指針一級指針目標變量二級間接尋址語言程序設計教程第二版

第九章指針C定義形式:[存儲類型]數(shù)據(jù)類型**指針名;如char**p;例

inti,**p;p=&i;()//p是二級指針,不能用變量地址為其賦值指針本身的存儲類型最終目標變量的數(shù)據(jù)類型*p是p間接指向對象的地址**p是p間接指向對象的值例

inti=3;

int*p1;

int

**p2;p1=&i;p2=&p1;**p=5;p1p2i3**p2,*p1*p2多級指針例三級指針int***p;

四級指針char****p;108020002020108020005語言程序設計教程第二版

第九章指針C【例】利用二級指針來處理字符串#include<stdio.h>#defineNULL0voidmain(){char**p;char*name[]={"hello","good","world","bye",""};p=name+1;

printf("%x:%s",*p,*p);p+=2;while(**p!=NULL)

printf("%s\n",*p++);}name[0]name[1]name[2]name[3]name[4]'h''e''l''l''o'0

'g''o''o''d'0

'w''o''r''l''d'0'b''y''e'00

p運行結果:42003C:goodpbyep用*p可輸出地址(%o或%x),也可用它輸出字符串(%s)注意:二級指針與指針數(shù)組的關系:int**p與int*q[10指針數(shù)組名是二級指針常量;

p=q;p+i是q[i]的地址;指針數(shù)組作形參時,int*q[]與int**q完全等價;但作為變量定義兩者不同。系統(tǒng)只給p分配能保存一個指針值的內(nèi)存區(qū);而給q分配10塊內(nèi)存區(qū),每塊可保存一個指針值。語言程序設計教程第二版

第九章指針C9.7指針作為函數(shù)的參數(shù)

參數(shù)傳遞方式:傳值

溫馨提示

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

評論

0/150

提交評論