C語言程序設計課件:指針_第1頁
C語言程序設計課件:指針_第2頁
C語言程序設計課件:指針_第3頁
C語言程序設計課件:指針_第4頁
C語言程序設計課件:指針_第5頁
已閱讀5頁,還剩48頁未讀 繼續免費閱讀

下載本文檔

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

文檔簡介

C語言程序設計

指針10.1指針概念

10.1.1指針定義

10.1.2指針初始化

10.1.3指針運算符

10.2指針變量運算

10.2.1指針變量賦值運算

10.2.2指針變量的算術運算

10.2.3指針變量間的關系運算

10.3指針和數組

10.3.1數組指針變量

10.3.2指針與一維數組

10.3.3指針與二維數組

10.3.4指針數組

10.4指針和函數

10.4.1指針作為函數參數

10.4.2指針作為函數返回值

10.4.3指針型函數

10.4.4函數指針變量

10.5指針與字符串

10.5.1字符串表示方法

10.5.2字符串處理函數的實現

10.6多重指針

10.6.1指向指針的指針

10.6.2命令行參數

內存單元的編號也叫做地址。根據內存單元的編號即地址就可以找到所需的內存單元,通常也把這個地址稱為指針。2.變量的“直接訪問”方式10.1指針概念

直接訪問:按變量地址存取變量值間接訪問:通過存放變量地址的變量去訪問變量例

i=3;-----直接訪問指針變量…...…...2000200420062005整型變量i10變量i_pointer20012002200320003例*i_pointer=20;-----間接訪問20指針變量…...…...2000200420062005整型變量i10變量i_pointer2001200220032000整型變量k例

k=i;--直接訪問

k=*i_pointer;--間接訪問10例

k=i;k=*i_pointer;與簡單變量一樣,指針變量也必須先定義后使用.指針變量定義的一般格式:類型名*變量名;例如:

int*pa;(pa是指向整型變量的指針變量)

char*pb;(pb是指向字符型變量的指針變量)

定義了名字為pa、pb的兩個指向不同類型數據的指針變量。

10.1.1指針定義

指針變量的初始化的一般形式為數據類型*指針變量名=初始地址值;例如:

int*pa=&i;在指針變量初始化中,通常用“&變量名”來表示一個基本類型變量的地址。在定義指針變量pa的同時,把變量i的地址作為初值來初始化pa。應注意的是,初始化中的“*pa=&i”不是運算表達式,而是一個說明語句。在這里將變量i的地址值賦給指針變量pa,而不是*pa。10.1.2指針初始化

注意:(1)指針目標變量的數據類型必須與指針的數據類型相一致。類型不一致將引起致命錯誤。例如,下面的初始化方式就是錯誤的,導致錯誤的原因就是類型不一致。

doublea:

int*pa=&a;(2)當把一個變量的地址作為初值賦給指針變量時,這個變量必須在這個指針初始化之前定義過。注意:(3)可以將一個指針的值賦給另一個指針變量。例如:

intb;

int*pb=&b;

int*q=pb;(4)可以把一個指針初的化為一個空指針。例如:

int*px=NULL;/*px是指針變量,初值為NULL,不指向任何目標*/(1)取地址運算符&取地址運算符&是單目運算符,其結合性為自右至左,其功能是取變量所占用的存儲單元的首地址。例如,

inti,*i_pointer;

i_pointer=&i;將變量i的地址(注意不是i的值)賦給i_pointer。這個賦值語句可以理解為i_pointer接受i的地址。如果給i分配的地址是2000開始的單元,則賦值后i_pointer的值是200010.1.3指針運算符

(2)取內容運算符*取內容運算符*是單目運算符,其結合性為自右至左,它的作用是通過指針變量來訪問它所指向的變量(存數據或取數據)。故在*運算符之后跟的變量必須是指針變量。i_pointer中存放i的地址,現賦值i=5;i_pointer=&i;j=*i_pointer;這個賦值語句可以理解為把i_pointer中存放的值當做地址,然后取那個地址(i的地址)中的值賦給變量j,結果是把“5”賦給j。常見的指針賦值運算有以下幾種形式。(1)把一個變量的地址賦給指向相同數據類型的指針變量。例如:

inta,*pa;

pa=&a;(2)相同數據類型的指針變量間可以相互賦值。例如:

int*p,*q;

q=p;(3)把數組的地址賦給指向相同數據類型的指針變量。例如:

doublex[10],*pa,*pb;

pa=x;

pb=&x[0];10.2指針變量運算

10.2.1指針變量賦值運算

(4)把數組的首地址賦予指向數組元素的指針變量。例如:

inta[5],*pa;

pa=a;數組名表示數組的首地址,故可賦予指向數組元素的指針變量pa。(5)把字符串的首地址賦予指向字符類型的指針變量。例如:

char*pc;

pc="clanguage";或用初始化賦值的方法寫為:char*pc="CLanguage";(6)把函數的入口地址賦予指向函數的指針變量。例如:int(*pf)();

pf=f;/*f為函數名*/在使用賦值運算時,不要將一個整數(整數0除外)或其他類型的數是不合法的。

inta,*p1;

float*p;

p1=100;

p1=a;另外,賦值語句p=p1;也是錯誤的。p和p1雖然都是指針變量,但分別指向不同類型的目標變量。可以將整數0賦予一個指針變量例如:pa=0;這時指針變量pa的值為0,表示該指針為空指針。空指針并不是指針的存儲空間為空。而是有著特定的值---0,它表示指針的一種狀態,即該指針不指向任何目標變量。

注意:在程序中使用指針變量之前,一定要給該指針賦予確定的地址值。一個沒有賦值的指針其指向是不定的。在使用指向不定的指針處理數據時,常常會破壞內存中其他領域的內容,嚴重時會造成系統失控。因此在程序中不要使用指向不定的指針。加減算術運算指針變量作為地址量加上或減去一個整數n,表示指針變量當前位置前移或后移n個存儲單元。例如:int*pn;不妨設pn=0x0000,那么pn+n=pn+n*sizeof(int)=0x0000+n*2。一般說來,對于“type*pn;”來說,“pn+n”表示的地址是“pn+n*sizeof(type)”,其中Type是某種數據類型,如整型、實型或字符型等。10.2.2指針變量的算術運算

指針變指針變量自增(++)、自減(--)運算指針變量自增(++)和自減(--)運算也是地址運算,指針變量自增(++)運算后就指向內存中下一個數據位置,指針變量自減(--)運算后就指向內存中上一個數據位置。運算后指針變量地址值也取決于它所指向的數據類型。指針變量的“++”、“--”運算也分為前置運算和后置運算,當它們和其他運算符出現在—個表達式中的時候,要注意它們之間的結合規則和運算順序。例如:y=*p++;

y=*++p;y=(*p)++;

y=++(*p);設指針變量p1和p2指向同類型的數據,則“p2-p1”運算的結果是兩個指針變量所指向的地址位置之間的數據個數。例如:type*p1,*p2;則p2-p1=(p2-p1)/sizeof(type)兩個指針變量相減也是地址計算,但結果值不是地址量,是按公式計算得到的一個整數。其中,“sizeof(type)”是表示指針變量的數據類型所占的字節數。10.2.3指針變量間的關系運算

指向相同數據類型的指針變量之間可以進行各種關系運算。兩個指針變量之間的關系運算表示它們的目標變量的地址位置之間的關系。假設數據在內存中的存儲邏輯是由前向后,則指向后方的指針變量大于前方的指針變量。例如:p<qp=q指向不同數據類型的指針變量之間的關系運算是沒有意義的。指針變量與一般整數變量之間的關系運算也是沒有意義的。但是指針變量可以和整數0之間進行等于或不等于的關系運算,用以判斷指針變量是否為空指針,即無效指針。例如:p==0或p!=010.3指針和數組

10.3.1數組指針變量定義一個指向數組元素的指針變量的方法,與以前介紹的指向變量的指針變量相同。inta[10];/*定義a為包含10個整型數據的數組*/int*p;/*定義p為指向整型變量的指針變量*/p=&a[0];/*把a[0]素的地址賦給指針變量p*/注意:

因為數組為int型,所以指針變量也應為指向int型的指針變量。通過指針引用數組元素C語言規定:如果指針變量p指向數組中的一個元素,則p+1指向同一數組中的下一個元素。例如,若p的初值為&a[0],則:

①p+i和a+i就是a[i]的地址,或者說它們指向a數組的第i個元素。

②*(p+i)或*(a+i)就是p+i或a+i所指向的數組元素,即a[i]。例如,*(p+5)或*(a+5)就是a[5]。

③指向數組的指針變量也可以帶下標,如p[i]與*(p+i)等價。

引用一個數組元素方法:

①下標法,即用a[i]形式訪問數組元素。在前面介紹數組時都是采用這種方法。

②指針法,即采用*(a+i)或*(p+i)形式,用間接訪問的方法來訪問數組元素,其中a是數組名,p是指向數組的指針變量,其初值p=a。用3種方法比較如下:(1)第①和②兩種方法執行效率相同。C編譯系統將a[i]轉換成*(a+i)進行處理。即先計算元素地址。因此用這兩種方法找出數組元素比較費時。(2)用第③種方法比第①、第②方法快,用指針變量直接指向元素,不需要每次都重新計算地址,像p++這樣的自加是比較快的,能大大提高執行效率。(3)用下標法比較直觀,能直接知道是第幾個元素。例如,a[5]是數組中的第6個元素。用地址法或指針變量的方法不直觀,難以很快判斷出當前處理的是哪個元素。例10-2用指針訪問數組元素。voidmain(){inta[10],i,*p;p=a;for(i=0;i<10;i++){*p=i;p++;}}注意:(1)指針變量可以實現本身的值的改變。如p++是合法的;而a++是錯誤的。(2)要注意指針變量的當前值。(3)雖然定義數組時,指定它包含10個元素,但指針變量可以指到數組以后的內存單元,系統并不認為非法。(4)*p++,由于++和*同優先級,結合方向自右而左,等價于*(p++)(5)*(p++)與*(++p)作用不同。若p的初值為a,則*(p++)等價于a[0],*(++p)等價a[1]。(6)(*p)++表示p所指向的元素值加1。(7)如果p當前指向a數組中的第i個元素,則:

*(p--)相當于a[i--];

*(++p)相當于a[++i];

*(--p)相當于a[--i]。10.3.2指針與一維數組一維數組和指針定義如下:inta[4]={1,2,3,4};int*p=a; /*p是指向一維數組元素的指針*/應用指針運算符+、*、[]建立指針與一維數組的關系,如圖10-4所示。a[i]、*(a+i)、*(p+i)、p[i]是等價表達式,均表示數組元素。a+i、p+i也是等價表達式,均表示數組元素的地址。要特別注意,p[i]表達式中的p不是數組名,是指針;這是一種下標表示法。10.3.3指針與二維數組1.指向二維數組元素的指針變量例10-4用指針變量輸出二維數組元素的值#include<stdio.h>voidmain(){inta[3][4]={1,2,,3,4,5,6,7,8,9,10,11,12};int*p;for(p=a[0];p<a[0]+12;p++){if((p-a[0])%4==0)printf(“\n”);printf(“%4d”,*p);}}

二維數組元素在內存中是以一維方式存儲。應用指向二維數組元素的指針,可以很方便地對二維數組實現一維運算從上圖可以看到有兩個方向的控制:①a、a+i、&a[i]控制的是行,或者說它們是行控制。②*(a+i)+j或a[i]+j控制的是列,即列控制。③雖然a+1和a[1]的值均是1020,但含義(屬性)是不一樣的。a+1指向a[1],是向縱向移動;a[1]指向a[1][0],是向橫向移動。

10.3.4指針數組

一個數組的元素為指針則是指針數組。指針數組是一組有序的指針的集合。指針數組的所有元素都必須是具有相同存儲類型和指向相同數據類型的指針變量。數組的元素是指針類型的,指針數組定義的一般格式:

類型*數組名[常量表達式];其中類型說明符為指針值所指向的變量的類型。例如:int*pa[3];表示pa是一個指針數組,它有三個數組元素,每個元素值都是一個指針,指向整型變量。10.4指針和函數

例10-7交換兩個整數—指針與函數。#include<stdio.h>/*形參不是指針,無法修改實參,達不到交換兩個整數的目的*/voidswapa(intx,inty);/*形參是指針,由于是修改指針本身,也達不到交換兩個整數的目的*/voidswapb(int*px,int*py);/*形參是指針,由于是修改指針所指向的目標,能達到交換兩個整數的目的*/

10.4.1指針作為函數參數

voidswapc(int*px,int*py);voidmain() {intx=10,y=20;printf("源數據(地址和值):\n");printf("x:%x%d\n",&x,x);printf("y:%x%d\n",&y,y);printf("調用swap1:\n");swapa(x,y);printf("在main函數內x=%dy=%d\n",x,y);printf("調用swapb:\n");swapb(&x,&y);printf("在main函數內x=%dy=%d\n",x,y);printf("調用swapc:\n");swapc(&x,&y);printf("在main函數內x=%dy=%d\n",x,y);}/*交換兩個整數--交換形參值*/voidswapa(intx,inty){ inttemp;temp=x;x=y;y=temp; printf("在swap1函數內x=%dy=%d\n",x,y);}/*交換兩個整數--交換形參值(地址)*/voidswapb(int*px,int*py){ int*temp;temp=px;px=py;py=temp; printf("在swapb函數內x=%dy=%d\n",*px,*py);}/*交換兩個整數--交換實參值*/voidswapc(int*px,int*py){ inttemp; temp=*px;*px=*py;*py=temp; printf("在swapc函數內x=%dy=%d\n",*px,*py);}

指針可作為函數的返回值類型。在處理動態數據結構時,經常遇到返回指針的函數。必須十分明確,數組不可作為函數的返回值類型。返回指針類型函數的一般格式:類型名*函數名(形參表); (有參函數)類型名*函數名(); (無參函數)return語句中,返回局部變量的地址是不允許的。因為函數返回,局部變量自動撤消。動態變量的地址、全局變量的地址和靜態變量的地址都可作為函數的返回值。

返回指針的函數,在字符串一小節和結構一章可看到實用的例題。這里借用一個無意義的例題說明概念。10.4.2指針作為函數返回值

例10-8返回局部變量的地址。#include<stdio.h>int*getint();/*指針函數*/voidmain() {int*p;p=getint();printf("p:%x(地址)%d(值)\n",p,*p);}/*返回局部變量的地址*/int*getint(){intvalue=20; /*局部變量*/printf("value:%x(地址)%d(值)\n",&value,value);return&value;/*警告錯誤!返回局部變量的地址*/}定義指針型函數的一般形式為:

類型說明符*函數名(形參表){……/*函數體*/}其中函數名之前加了“*”號表明這是一個指針型函數,即返回值是一個指針。類型說明符表示了返回的指針值所指向的數據類型。如:int*ap(intx,inty){…/*函數體*/}

10.4.3指針型函數

例10-9指針函數應用舉例,輸出對應的星期幾。

voidmain(){inti;char*day_name(intn);printf("inputDayNo:\n");scanf("%d",&i);if(i<0)exit(1);printf("DayNo:%2d-->%s\n",i,day_name(i));}char*day_name(intn){staticchar*name[]={"Illegalday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"};return((n<1||n>7)?name[0]:name[n]);}10.4.4函數指針變量指向函數的指針稱為函數指針。函數指針是函數的入口地址。可用函數指針調用函數。函數指針也可作為函數的形參。函數指針的一般定義格式:類型名(*指針變量名)(); (無參數表)類型名(*指針變量名)(類型名表); (有參數表)類型名是指函數返回值的類型。調用函數的一般格式:(*指針變量名)(實參表);(*指針變量名)表示“*”后面的變量是定義的指針變量。最后的空括號表示指針變量所指的是一個函數。例如:int(*pf)();表示pf是一個指向函數入口的指針變量,該函數的返回值(函數值)是整型。

10.4.4函數指針變量例10-10求a和b中較大者,用函數指針實現。

#include<stdio.h>intmax(inta,intb){if(a>b)returna;elsereturnb;}voidmain(){intmax(inta,intb);int(*pmax)();intx,y,z;pmax=max;printf("inputtwonumbers:\n");scanf("%d%d",&x,&y);z=(*pmax)(x,y);printf("maxmum=%d",z);}10.5指針與字符串10.5.1

字符串表示方法字符指針初始化的方法有如下兩種形式:在定義字符型指針時,可以用字符串常量初始化。例如:char*strp="VC++";字符串常量可以賦給字符型指針變量。例如:char*strp;strp="VC++";字符串表示方法例10-11通過字符指針輸出一個字符串。#include<stdio.h>voidmain(){char*ps;ps="CLanguage";printf("%s",ps);}首先定義ps是一個字符指針變量,然后把字符串的首地址賦予ps(應寫出整個字符串,以便編譯系統把該串裝入連續的一塊內存單元),并把首地址送入ps。程序中的:char*ps;ps="CLanguage";等效于:char*ps="CLanguage";輸出字符串中的所有字符。字符串表示方法例10-12在輸入的字符串中查找有無'k'字符。#include<stdio.h>voidmain(){charst[20],*ps;inti;printf("inputastring:\n");ps=st;scanf("%s",ps);for(i=0;ps[i]!='\0';i++)if(ps[i]=='k'){printf("thereisa'k'inthestring\n");break;}if(ps[i]=='\0')printf("Thereisno'k'inthestring\n");}10.5.2字符串處理函數的實現1.求字符串長度函數原型unsignedintstrlen(constchar*s); unsignedintstrlen(constchar*s) { intlen=0; while(*s++)len++;

returnlen; }執行*s++表達式等價于:

*s 先取s指針所指向的字符。

s++ 再s指針加1,指向下一字符。2.字符串復制函數原型char*strcpy(char*dest,constchar*src);字符串復制是將原字符串src一個字符一個字符地復制到目標串dest,包含'\0'字符。最后返回指針temp,即返回dest原指針值。*dest++和*src++是左值表達式。執行*dest++=*src++表達式等價于:*dest=*src 先將指針src指向的字符復制到指針dest指向的存儲單元。src++ src 指針加1,指向下一字符。dest++ des 指針加1,指向下一字符。注意,由于先執行賦值,然后src指針和des指針再加1,所以’\0’字符能復制。3.字符串連接

函數原型 char*strcat(char*dest,constchar*src);字符串連接是先將指針dest移到字符'\0'處,然后將src串復制到指針dest指向的存儲單元。最后返回指針temp,即返回dest原指針。圖7-12描述了字符串連接過程。

4.字符串比較

函數原型 int strcmp(constchar*s1,constchar*s2);兩個字符串比較是對應字符一一比較。當兩個字符不等或兩個字符均為'\0'時,結束比較,返回*s1-*s2。當前兩個字符的值決定了兩個字符串比較關系與返回值:*s1==*s2,*s1=='\0',*s2=='\0' 串1==串2 返回值為0*s1>*s2

串1>串2 返回大于0*s1<*s2 串1<串2 返回小于0因此,函數strcmp的返回值能決定了兩個字符串比

溫馨提示

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

評論

0/150

提交評論