版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認(rèn)領(lǐng)
文檔簡介
C語言程序設(shè)計智能工程學(xué)院“現(xiàn)場課程”
目
錄目錄CONTENTS
指針的概念8.1
指針變量8.2
8.1指針的概念
核心概念定義
一個變量的地址稱為該變量的“指針”。如果有一個變量專門用來存放其他變量的地址(指針),這個變量被稱為“指針變量”。
變量地址:以整型變量為例,若其占據(jù)4個字節(jié),這4個字節(jié)中編號最小的字節(jié)的地址,即為該整型變量的地址,也稱為其“首地址”。
指針:變量的地址就叫做該變量的“指針”。例如整型變量a的地址,可直接記作&a,&a就是變量a的指針。
指針變量:專門用于存放其他變量地址(即指針)的變量,被稱為“指針變量”。
實例說明
以整型變量inta=247為例,具體解釋上述概念:1.變量a在內(nèi)存中占據(jù)4個連續(xù)字節(jié),用于存儲數(shù)值247。2.假設(shè)這4個字節(jié)的起始地址(首地址)為0012FF7C,那么變量a的地址就是0012FF7C。3.這個地址0012FF7C既是變量a的首地址,也是變量a的指針,按規(guī)定寫法記為&a。訪問變量的方式可分為兩種,一種是“直接訪問”方式,另一種是“間接訪問”方式。按變量名訪問的方式稱為“直接訪問”方式。例如,圖所示即為直接訪問方式,通過變量名a直接賦值,由于變量名與變量的地址一一對應(yīng),因此,直接將數(shù)值1放到變量a的存儲單元中。
8.1指針的概念如果將變量a的地址存放在另一變量中,然后通過該變量來找到變量a的地址,從而訪問變量a,這就是“間接訪問”方式。例如,圖所示即為間接訪問方式,先找到存放變量a地址的變量p,從其中得到變量a的地址(2000),從而找到變量a的存儲單元,然后對它進行存取訪問。這就好比要取抽屜a中的東西,需要先用抽屜p的鑰匙打開抽屜p,從抽屜p中取出抽屜a的鑰匙,再打開抽屜a。
提示一個變量的地址稱為該變量的“指針”。例如,地址2000是變量a的指針。專門用來存放另一變量地址(即指針)的變量稱為“指針變量”。例如,上述變量p就是一個指針變量?!爸羔槨笔且粋€地址,而“指針變量”是存放地址的變量。注意區(qū)分兩者的概念。
8.1指針的概念指針變量與一般變量一樣,必須“先定義后使用”。定義一個指針變量需要解決兩個問題:一是說明指針變量的名字,二是說明指針變量指向變量的數(shù)據(jù)類型。定義指針變量的一般形式為:類型說明符*指針變量名1,*指針變量名2…;例如:int*p1; /*定義指向整型變量的指針變量p1*/char*p2,*p3; /*定義指向字符型變量的指針變量p2和p3*/其他類型的變量允許和指針變量在同一個語句中定義,例如:intm,*p; /*定義2個變量,其中m是整型變量,p是指向整型變量的指針變量*/
8.2指針變量8.2.1指針變量定義
提示1)在定義時,指針變量名前的“*”表示該變量的類型是指針型變量,不能省略。(2)指針變量定義中的“數(shù)據(jù)類型”是指針指向的目標(biāo)數(shù)據(jù)的類型。讀者可能會提出,既然指針變量是存放地址的,那么為什么要指定數(shù)據(jù)類型呢?我們知道,不同類型的數(shù)據(jù)在內(nèi)存中所占的字節(jié)數(shù)和存放方式是不一樣的。例如,字符型數(shù)據(jù)占1個字節(jié),整型數(shù)據(jù)占4個字節(jié)。因此,如果想通過指針引用一個變量,只知道地址(如2000)是不夠的,因為無法判斷是從地址為2000的一個字節(jié)中取出字符型數(shù)據(jù),還是從2000到2003四個字節(jié)中取出整型數(shù)據(jù)。
8.2指針變量8.2.1指針變量定義可以在定義指針變量的同時為其賦初值,即指針變量的初始化。由于指針變量是指針類型,因此,所賦初值應(yīng)是一個地址值。其一般格式為:類型說明符*指針變量名1=地址1,*指針變量名2=地址2…;例如:inti;int*p=&i; /*定義指針變量p指向整型變量i*/表示地址的形式可以是“&變量名”“數(shù)組名”“其他指針變量”等。例如:chars[20];char*str=s; /*定義指針變量str指向字符數(shù)組s的首地址*/
8.2指針變量8.2.2
指針變量初始化在引用指針變量時,一般有3種情況。給指針變量賦值1在程序執(zhí)行過程中,可以使用賦值語句為指針變量賦值,一般格式為:指針變量=地址;例如:inta=20,b=30,*p1,*p2;p1=&a; /*把變量a的地址賦給指針變量p1*/p2=&b; /*把變量b的地址賦給指針變量p2*/
8.2指針變量8.2.3
指針變量引用定義了兩個整型變量a和b,a初值為20,b初值為30;定義了指針變量p1指向變量a,指針變量p2指向變量b,其相互之間的關(guān)系如左圖所示。指針變量和一般變量一樣,存放在它們之中的值是可以改變的,也就是說,可以改變它們的指向,例如,執(zhí)行表達(dá)式語句“p2=p1;”,意思是p2與p1指向同一對象a,此時*p2就等價于a,而不是b,如右圖所示。
8.2指針變量8.2.3
指針變量引用
名師點睛要熟練掌握兩個有關(guān)的運算符:(1)“&”運算符是取地址運算符,它是單目運算符,其功能是返回其后所跟操作數(shù)的地址,其結(jié)合性為從右向左。例如,&a是變量a的地址。(2)“*”運算符是指針運算符,也稱間接運算符,它也是單目運算符。其功能是取該指針指向的存儲單元的值。例如,*p代表指針變量p指向的對象。
8.2指針變量8.2.3
指針變量引用引用指針變量指向的變量2如果在上述定義語句后面執(zhí)行表達(dá)式語句“*p2=*p1;”,即:inta=20,b=30,*p1,*p2;p1=&a; /*把變量a的地址賦給指針變量p1*/p2=&b; /*把變量b的地址賦給指針變量p2*/*p2=*p1; /*引用指針變量指向的變量*/則表示把p1指向的內(nèi)容賦給p2所指的區(qū)域,即等價于“b=a;”,如圖所示。
8.2指針變量8.2.3
指針變量引用【例8-1】有下列代碼,試分析輸出結(jié)果。#include<stdio.h>intmain(){ intx=10,*p,y; p=&x; /*取變量x的地址賦給指針變量p*/ y=*p; /*將*p的值賦給y*/ printf("x=%d,*p=%d,y=%d\n",x,*p,y); /*輸出x,*p和y的值*/ printf("&x=%x,p=%x,&y=%x\n",&x,p,&y); /*輸出x和y的地址以及指針p的值*/ return0;}引用指針變量的值3用十六進制形式輸出指針變量p的值,即輸出a的地址,可以用如下語句實現(xiàn)。inta;int*p=&a;printf("%x",p);
8.2指針變量8.2.3
指針變量引用【程序說明】此例中定義了三個變量,x和y為整型變量,p為指針變量。x的初值為10,讓p去指向x,*p表示取指針變量p所指存儲單元的內(nèi)容,即變量x的值,因此,*p和y也等于10。p為指針變量且指向x,因此,p即為x的地址;y和x是不同的變量,因此,它們所占的存儲空間不同,即地址不同。
8.2指針變量8.2.3
指針變量引用【運行結(jié)果】程序運行結(jié)果如圖所示。
提示此例中第4行和第6行都出現(xiàn)了“*p”,但意義是不同的?!癷ntx=10,*p,y;”語句中的“*p”表示將變量p聲明為指針變量,用“*”以區(qū)別于一般變量。而“y=*p;”中的“*p”表示使用指針變量p,此時“*”是運算符,表示取指針?biāo)赶虻拇鎯卧獌?nèi)容,即對p進行間接存取運算,取變量x的值。
8.2指針變量8.2.3
指針變量引用空指針1不指向任何對象的指針即為空指針,表示該指針沒有指向任何內(nèi)存單元。構(gòu)造空指針有下面兩種方法。(1)賦0值。例如:int*p=0;
名師點睛除0之外,一般不把其他整數(shù)作為初值賦給指針變量。程序運行期間,變量的地址是由計算機分配的,當(dāng)用一個整數(shù)為一個指針變量賦初值后,可能會造成難以預(yù)料的后果。
8.2指針變量8.2.4
空指針與void指針(2)賦NULL值,NULL的值等于0,兩者等價。例如:int*p=NULL;空指針常用來初始化指針,避免野指針的出現(xiàn)。對指針變量賦0值和不賦值是不同的。指針變量未賦值時,可以是任意值,是不能使用的,否則將造成意外錯誤。而指針變量賦0值后,則可以使用,只是它不指向具體的變量。void指針2C語言規(guī)定,指針變量也可以定義為void型,例如:void*p;這里p仍然是一個指針變量,有自己的內(nèi)存空間。但是不指定p指向哪種類型的變量。在這種情況下,應(yīng)該注意:
8.2指針變量8.2.4
空指針與void指針(1)任何指針都可以賦值給void指針。例如:intx=10;int*q=&x;p=q; /*不需要進行強制類型轉(zhuǎn)換*/(2)使用void指針時必須對其進行強制類型轉(zhuǎn)換,將void指針轉(zhuǎn)換成它所指向單元的實際類型,然后才可以使用。因此,void指針賦值給其他類型的指針時要進行強制類型轉(zhuǎn)換。例如:int*t=(int*)p; /*需要進行強制類型轉(zhuǎn)換*/printf("*p=%d",*(int*)p); /*輸出p指向的存儲單元內(nèi)容*/指針是內(nèi)存單元的地址,指針變量就是存放指針的變量。不同數(shù)據(jù)類型在內(nèi)存中所占內(nèi)存單元的大小是不一樣的,但是地址卻是一樣的,即使用該數(shù)據(jù)在內(nèi)存單元中的首地址。因此,用void指針來存放這個首地址與數(shù)據(jù)類型無關(guān)。但是,當(dāng)要使用這個數(shù)據(jù)時,通過指針訪問內(nèi)存單元,系統(tǒng)不僅需要知道內(nèi)存單元的首地址,而且還要知道這個數(shù)據(jù)在內(nèi)存中所占的存儲單元的大小,因此,在使用void指針時必須對指針進行強制類型轉(zhuǎn)換。
8.2指針變量8.2.4
空指針與void指針
目
錄目錄CONTENTS
指針與數(shù)組8.3定義指向一維數(shù)組的指針變量1從第7章中我們了解到,定義完一個一維數(shù)組后,每個數(shù)組元素就相當(dāng)于一個變量。既然指針變量可以指向一般的變量,那么當(dāng)然也可以指向數(shù)組中的元素。例如:inta[5]={1,2,3,4,5},*p;p=&a[0];以上代碼的功能是定義一個一維數(shù)組和一個指針變量p,使指針變量p指向數(shù)組a的第0號元素(即第1個元素),如圖所示。
8.3指針與數(shù)組8.3.1
指針與一維數(shù)組由于一維數(shù)組的數(shù)組名是一個地址常量,程序運行時它的值是一維數(shù)組第1個元素的地址。因此,我們可以通過數(shù)組名將數(shù)組的首地址賦給指針變量,即:“p=a;”與“p=&a[0];”等價。
提示由上述分析可知,p,a和&a[0]均指向同一單元,它們是數(shù)組a的首地址,也是數(shù)組a的第0號元素a[0]的地址。但應(yīng)該說明的是,p是變量,而a和&a[0]都是常量。
8.3指針與數(shù)組8.3.1
指針與一維數(shù)組數(shù)組中的指針運算2當(dāng)指針指向數(shù)組元素時,可以對指針進行以下運算。1)加減一個整數(shù)對于指向數(shù)組的指針變量,可以加上或減去一個整數(shù)n。例如,設(shè)p是指向數(shù)組a的指針變量,則p+n,p-n,p++,++p,p--,--p都是合法的。指針變量加或減一個整數(shù)n的意義是:把指針指向的當(dāng)前位置(指向某數(shù)組元素)向前或向后移動n個位置。這里加減的單位不是以字節(jié)為單位,而是以指向的數(shù)據(jù)類型所占用的字節(jié)數(shù)為單位。例如,在VisualC++環(huán)境下,int變量占4個字節(jié),double型變量占8個字節(jié)。因此,如果p指向整型數(shù)組,p+n表示的實際地址為“p+4*n”。
8.3指針與數(shù)組8.3.1
指針與一維數(shù)組【例8-2】分析下面程序運行結(jié)果。#include<stdio.h>intmain(){ inta[5]={1,2,3,4,5}; int*p=a; printf("ais:%X,a+1is:%X\n",a,a+1); printf("pis:%X,p+1is:%X\n",p,p+1); printf("*ais:%d,*(a+1)is:%d\n",*a,*(a+1)); printf("*pis:%d,*(p+1)is:%d\n",*p,*(p+1)); return0;}
8.3指針與數(shù)組8.3.1
指針與一維數(shù)組【運行結(jié)果】程序運行結(jié)果如圖所示。
8.3指針與數(shù)組8.3.1
指針與一維數(shù)組【程序說明】此例中p的初值為a,即&a[0],則p+n和a+n就是數(shù)組元素a[n]的地址,或者說,它們指向數(shù)組a序號為n的元素,如圖所示。這里需要注意的是:a代表數(shù)組首元素的地址,a+1也是地址,它的計算方法同p+1,即它的實際地址為a+1*4。*(p+n)或*(a+n)是p+n或a+n所指向的數(shù)組元素,即a[n]。例如,*(p+1)或*(a+1)就是a[1]。
8.3指針與數(shù)組8.3.1
指針與一維數(shù)組2)兩指針變量相減如果兩個指針變量指向同一數(shù)組,則兩個指針變量相減所得之差就是兩個指針?biāo)笖?shù)組元素之間相差的元素個數(shù)。實際上是兩個指針值(地址)相減之差再除以該數(shù)組元素的長度(字節(jié)數(shù))。例如,p1和p2是指向同一整型數(shù)組的兩個指針變量,設(shè)p1的值為2008H,p2的值為2000H,而整型數(shù)組每個元素占4個字節(jié),則p1-p2的結(jié)果為(2008H-2000H)/4=2,表示p1和p2之間相差2個元素。
名師點睛(1)只有指向同一數(shù)組的兩個指針變量之間才能進行減法運算,否則毫無意義。(2)兩個指針變量不能進行加法運算。例如,p1+p2是無實際意義的。
8.3指針與數(shù)組8.3.1
指針與一維數(shù)組【例8-3】編寫程序求字符串的長度,要求使用指針變量?!締栴}分析】可定義字符數(shù)組str用于存放字符串,定義指針變量p指向字符數(shù)組的首地址;然后利用循環(huán)語句找到字符串的結(jié)束標(biāo)志'\0',讓指針變量p指向'\0';這時可利用p-str得到字符串的長度。
8.3指針與數(shù)組8.3.1
指針與一維數(shù)組【參考代碼】#include<stdio.h>intmain(){ charstr[50],*p=str; /*定義字符數(shù)組str和指針變量p指向數(shù)組str*/ printf("Enterstring:"); /*輸出提示符*/ gets(str); /*輸入字符串*/ while(*p) /*p不為'\0'時循環(huán)*/ p++; /*找到串結(jié)束標(biāo)記'\0',退出循環(huán)時p指向'\0'*/ printf("Stringlength=%d\n",p-str); /*利用指針減法運算求出字符串長度*/ return0;}
8.3指針與數(shù)組8.3.1
指針與一維數(shù)組【運行結(jié)果】程序運行結(jié)果如圖所示。
8.3指針與數(shù)組8.3.1
指針與一維數(shù)組通過指針引用數(shù)組元素3引用一個數(shù)組元素有兩種方法。(1)下標(biāo)法,即a[i]的形式。(2)指針法,如*(a+i)或*(p+i)。其中,a是數(shù)組名,p是指向數(shù)組元素的指針變量,其初值p=a。指向數(shù)組的指針變量也可以帶下標(biāo),如p[i]與*(p+i)等價。
高手點撥*(p+i)和a[i]相等的前提條件是p指向數(shù)組a的首地址。如果賦值“p=&a[4];”,則p指向a[4],p+1指向a[5],而p-1指向a[3],也就是說,指針在數(shù)組中是可以移動的。
8.3指針與數(shù)組8.3.1
指針與一維數(shù)組【例8-4】#include<stdio.h>intmain(){ inta[5],*p,i; for(i=0;i<5;i++) a[i]=i+1; p=a; for(i=0;i<5;i++)分析下面程序運行結(jié)果。
8.3指針與數(shù)組8.3.1
指針與一維數(shù)組 printf("*(p+%d):%d\t",i,*(p+i)); for(i=0;i<5;i++) printf("*(a+%d):%d\t",i,*(a+i)); for(i=0;i<5;i++) printf("p[%d]:%d\t",i,p[i]); printf("\n"); for(i=0;i<5;i++) printf("a[%d]:%d\t",i,a[i]); printf("\n"); return0;}
8.3指針與數(shù)組8.3.1
指針與一維數(shù)組【運行結(jié)果】程序運行結(jié)果如圖所示。【程序說明】從程序運行結(jié)果中可以得出,*(p+i),*(a+i),p[i]和a[i]輸出的結(jié)果都是相同的。
8.3指針與數(shù)組8.3.1
指針與一維數(shù)組二維數(shù)組元素的地址1假設(shè)定義一個4行3列的二維數(shù)組,例如:inta[4][3];二維數(shù)組在邏輯上是由行和列組成的,因此,對二維數(shù)組可以將其分為3層來理解,如圖所示。第1層將數(shù)組a看作一個變量;第2層將二維數(shù)組a看作一個一維數(shù)組,由a[0],a[1],a[2]和a[3]這4個元素組成;第3層將第2層中的每個數(shù)組元素看作一個單獨的數(shù)組。在第1層中將數(shù)組a作為一個變量,該變量的地址為&a,變量長度為sizeof(a)。
8.3指針與數(shù)組8.3.2
指針與二維數(shù)組【例8-5】#include<stdio.h>intmain(){ inta[4][3]; /*定義二維數(shù)組*/ printf("變量a的地址:%d\n",&a); /*輸出a的地址*/ printf("變量a的長度:%d\n",sizeof(a)); /*輸出a所占的地址空間*/ return0;}分析下面程序運行結(jié)果。
8.3指針與數(shù)組8.3.2
指針與二維數(shù)組【運行結(jié)果】程序運行結(jié)果如圖所示。
8.3指針與數(shù)組8.3.2
指針與二維數(shù)組【程序說明】從程序運行結(jié)果可以看出,使用&運算符可取得數(shù)組名的地址(不同的計算機得到的地址值可能不同)。數(shù)組a的長度為元素數(shù)量乘以每個元素占用的字節(jié),4行3列共12個元素,每個元素占用4個字節(jié),所以變量a占用48個字節(jié)。在第2層中,將數(shù)組a看作為一維數(shù)組,它有4個元素a[0],a[1],a[2]和a[3]。數(shù)組的首地址為a或&a[0](第一個元素的地址也是首地址)。使用sizeof(a[0])可得到數(shù)組元素的長度。
8.3指針與數(shù)組8.3.2
指針與二維數(shù)組【例8-6】#include<stdio.h>intmain(){ inta[4][3],i; printf("數(shù)組a的首地址:%d\n",a); /*輸出數(shù)組首地址*/ for(i=0;i<4;i++) /*循環(huán)輸出數(shù)組元素地址*/ { printf("數(shù)組a第%d個元素的地址:%d\n",i+1,&a[i]); } printf("數(shù)組元素a[0]的長度:%d\n",sizeof(a[0])); /*輸出數(shù)組元素的長度*/ return0;}分析下面程序運行結(jié)果。
8.3指針與數(shù)組8.3.2
指針與二維數(shù)組【運行結(jié)果】程序運行結(jié)果如圖所示。
8.3指針與數(shù)組8.3.2
指針與二維數(shù)組【程序說明】以上程序?qū)?shù)組a看作一個一維數(shù)組,由4個元素組成。首先輸出數(shù)組首地址。然后,循環(huán)輸出4個數(shù)組元素的地址,從執(zhí)行結(jié)果可以看出,數(shù)組首地址和第一個元素的地址相同,而每個數(shù)組元素的地址相差為12,表示每個數(shù)組元素的長度為12。最后,程序使用sizeof(a[0])證實數(shù)組元素a[0]的長度的確為12。從以上結(jié)果可看出,將二維數(shù)組a作為一維數(shù)組看待時,其每個元素的長度就是二維數(shù)組中一行元素的長度之和。
8.3指針與數(shù)組8.3.2
指針與二維數(shù)組
提示輸出數(shù)組首地址時沒有使用取地址運算符,這是因為數(shù)組名就是一個指針常量。在其他計算機中運行該程序,得到的地址值可能不同,但每個元素地址之間的差值肯定是相同的。在第3層中,第2層中的每個元素又由3個元素構(gòu)成。例如,a[0]又由a[0][0],a[0][1]和a[0][2]這3個元素構(gòu)成。當(dāng)將a[0]作為一個數(shù)組名時,該數(shù)組的首地址也就保存在a[0]中(這里a[0]作為一個整體,看作數(shù)組名,不是一個數(shù)組的元素),不用取地址運算符&,直接輸出a[0]的值就可得到數(shù)組的首地址。
8.3指針與數(shù)組8.3.2
指針與二維數(shù)組【例8-7】#include<stdio.h>intmain(){ inta[4][3],i; printf("數(shù)組a的首地址:%d\n",a); /*輸出數(shù)組首地址*/ for(i=0;i<4;i++) { printf("數(shù)組a[%d]的首地址:%d\n",i,a[i]); /*輸出a[i]首地址*/ } for(i=0;i<3;i++) /*輸出第0行每個元素的地址*/ { printf("數(shù)組元素a[0][%d]地址:%d\n",i+1,&a[0][i]); } printf("數(shù)組元素a[0][0]的長度:%d\n",sizeof(a[0][0])); /*輸出a[0][0]的長度*/ return0;}分析下面程序運行結(jié)果。
8.3指針與數(shù)組8.3.2
指針與二維數(shù)組【運行結(jié)果】程序運行結(jié)果如圖所示。
8.3指針與數(shù)組8.3.2
指針與二維數(shù)組【程序說明】此程序?qū)?shù)組第2層中的每個元素作為數(shù)組名,通過程序循環(huán)輸出4個數(shù)組的首地址。將a[0],a[1],a[2]和a[3]分別看作4個單獨的數(shù)組,輸出數(shù)組a[0]中3個元素的地址。從輸出結(jié)果可以看出,每個元素相差4個字節(jié),即每個元素占用4個字節(jié),最后,從輸出元素a[0][0]長度的結(jié)果中驗證了這一點。既然可以將二維數(shù)組a看成一個一維數(shù)組,也就可以使用前面介紹的方法用指針方式來表示這個一維數(shù)組。例如,a+1就是數(shù)組a的第2個元素的地址,a+i就是它的第i+1個元素的地址,這樣,使用*(a+i)就可訪問該元素的值(等同于a[i])。進一步,在二維數(shù)組中,*(a+i)(即a[i])又指向一個數(shù)組,*(a+i)+j表示這個數(shù)組的第j+1個元素的地址,等同于a[i]+j;要訪問該元素的值可使用*(*(a+i)+j)或*(a[i]+j),也就是a[i][j]。
8.3指針與數(shù)組8.3.2
指針與二維數(shù)組綜上所述,二維數(shù)組中的有關(guān)指針如表所示。表示形式含義&a二維數(shù)組a的地址a二維數(shù)組名,指向一維數(shù)組a[0],即0行首地址a[0],*(a+0),*a0行0列元素地址&a[i],a+ii行首地址a[i],*(a+i)i行0列元素a[i][0]的地址a[i]+j,*(a+i)+j,&a[i][j]i行j列元素a[i][j]的地址*(a[i]+j),*(*(a+i)+j),a[i][j]i行j列元素a[i][j]的值
8.3指針與數(shù)組8.3.2
指針與二維數(shù)組
提示二維數(shù)組名a是指向行的,因此,a+1中的“1”代表一行中全部元素所占的字節(jié)數(shù)。一維數(shù)組名(如a[0])是指向列元素的,因此,a[0]+1中的“1”代表一個元素所占的字節(jié)數(shù)。在指向行的指針前加一個*,就是將其轉(zhuǎn)換為指向列的指針。例如,a+1是指向行的指針,在它們前面加一個*,即*(a+1)就是指向列的指針,意思是指向a數(shù)組1行0列的元素。反之,在指向列的指針前加&,就是將其轉(zhuǎn)換為指向行的指針。例如,a[0]是指向0行0列元素的指針,在它前面加一個&,即&a[0]就是指向二維數(shù)組的0行。
8.3指針與數(shù)組8.3.2
指針與二維數(shù)組指向數(shù)組元素的指針變量2可以用指針變量指向二維數(shù)組的元素,若有:inta[4][3],*p;p=&a[0][0];則二維數(shù)組a的數(shù)據(jù)元素在內(nèi)存中存儲順序、地址及指針變量p的關(guān)系如圖所示。
8.3指針與數(shù)組8.3.2
指針與二維數(shù)組從圖中,我們可以看出指針和二維數(shù)組元素的對應(yīng)關(guān)系。清楚了兩者之間的關(guān)系,就能用指針處理二維數(shù)組了。若有:inta[M][N];p=a[0];對于數(shù)組a中的任一元素a[i][j],指針的一般形式為:p+i*N+j;同樣,a[i][j]也可以使用指針下標(biāo)法表示:p[i*N+j]。
8.3指針與數(shù)組8.3.2
指針與二維數(shù)組【例8-8】求二維數(shù)組元素的最大值?!締栴}分析】此問題可以通過順序移動數(shù)組指針的方法來對數(shù)組元素進行遍歷,找出最大值并輸出。
8.3指針與數(shù)組8.3.2
指針與二維數(shù)組【參考代碼】#include<stdio.h>intmain(){ inta[4][3]={{2,12,5},{55,7,98},{10,36,6},{78,42,1}}; /*初始化二維數(shù)組*/ int*p=a[0]; /*定義指針變量p指向a[0]*/ intmax=*p; /*定義變量max用來存儲最大值,初始化為*p*/ while(p<a[0]+12) /*當(dāng)p<a[0]+12時循環(huán)*/ { if(*p>max) /*當(dāng)*p大于max時,將*p的值賦給max*/ max=*p; p++; /*p指向下一個數(shù)組元素*/ } printf("MAX=%d\n",max); /*輸出max的值*/ return0;}
8.3指針與數(shù)組8.3.2
指針與二維數(shù)組【運行結(jié)果】程序運行結(jié)果如圖所示?!境绦蛘f明】p是一個int型指針變量;p=a[0]是設(shè)置數(shù)組的首元素地址為指針初值;max=*p表示將數(shù)組的首元素值a[0][0]作為最大值初值;p<a[0]+12表示將指針的變化范圍限制在12個元素范圍內(nèi);p++使得每比較一個元素后,指針后移一個元素位置。
8.3指針與數(shù)組8.3.2
指針與二維數(shù)組指向一維數(shù)組的指針變量3我們還可以定義指針變量p指向一個包含N個元素的一維數(shù)組。這時,如果p先指向a[0](即p=&a[0]),則p+1不是指向a[0][1],而是指向a[1],p的增值以一維數(shù)組的長度為單位,如圖所示。
8.3指針與數(shù)組8.3.2
指針與二維數(shù)組圖中,指針p指向的數(shù)據(jù)類型應(yīng)該是一個具有3個int元素的數(shù)組。因此,應(yīng)使用以下方式定義該指針變量:int(*p)[3];這種方式稱為數(shù)組指針,即定義的變量是一個指針,其指向類型是一個數(shù)組。
提示*p必須用括號括起來,如寫成:“int*p[3];”,由于運算符[]的優(yōu)先級高于運算符*,因此,變量p先與[3]結(jié)合組成數(shù)組,然后再與前面的*號結(jié)合,這樣就成了指針數(shù)組(每個數(shù)組元素保存一個指針,這個將在本章后面進行介紹)。
8.3指針與數(shù)組8.3.2
指針與二維數(shù)組【例8-9】求二維數(shù)組元素的最大值,并確定最大值元素所在的行和列?!締栴}分析】本例較例8-8有更進一步的要求,需要在比較的過程中,把較大值元素的位置記錄下來,需要使用能提供行列數(shù)據(jù)的指針表示方法。
8.3指針與數(shù)組8.3.2
指針與二維數(shù)組【參考代碼】#include<stdio.h>intmain(){ inta[4][3]={{2,12,5},{55,7,98},{10,36,6},{78,42,1}};/*初始化二維數(shù)組*/ intmax,i,j,row,col; /*定義變量*/ int(*p)[3]; /*定義指向一維數(shù)組的指針變量*/ p=a; /*p指向二維數(shù)組的0行*/ max=a[0][0]; /*max的初始值為a[0][0]*/row=col=0; /*行號和列號初始值為0*/ for(i=0;i<4;i++) /*外循環(huán)控制行*/
8.3指針與數(shù)組8.3.2
指針與二維數(shù)組 for(j=0;j<3;j++) /*內(nèi)循環(huán)控制列*/ if(*(*(p+i)+j)>max) /*如果a[i][j]大于max*/ { max=*(*(p+i)+j); /*將其值賦給max*/ row=i; /*row為行號*/ col=j; /*col為列號*/ } printf("MAX=a[%d][%d]=%d\n",row,col,max); /*輸出最大值及其位置*/ return0;}
8.3指針與數(shù)組8.3.2
指針與二維數(shù)組【運行結(jié)果】程序運行結(jié)果如圖所示?!境绦蛘f明】該程序中使用雙重循環(huán)遍歷二維數(shù)組元素。在程序中,使用*(*(p+i)+j)的方式指向二維數(shù)組的某一個元素。在這里*(p+i)得到的是二維數(shù)組行的地址,相當(dāng)于a[i](注意是一個內(nèi)存地址值)。接著執(zhí)行*(p+i)+j,相當(dāng)于a[i]+j,也是一個地址值,表示第i行首地址加上j個元素的位置。最后使用*(*(p+i)+j)即可得到第i行第j列的元素值,相當(dāng)于a[i][j]。
8.3指針與數(shù)組8.3.2
指針與二維數(shù)組通過前面的學(xué)習(xí),我們知道字符串是存放在字符數(shù)組中的。要想引用一個字符串,可以有兩種方法。1用字符數(shù)組存放一個字符串,可以通過數(shù)組名和下標(biāo)引用字符串中的一個字符,也可以通過數(shù)組名和格式聲明“%s”輸出該字符串。例如:charstr[30]="Clanguage!"; /*定義字符數(shù)組str*/printf(“%c\n”,str[3]); /*用%c格式聲明輸出str[3]*/printf(“%s\n”,str); /*用%s格式聲明輸出str*/
8.3指針與數(shù)組8.3.2
指針與字符串2可以把字符數(shù)組的首地址賦給一個指針變量,那么這個指針變量則指向這個字符數(shù)組,使用該指針變量可以完成對字符數(shù)組的操作。此外,我們還可以利用字符串常量對字符指針進行初始化。例如:char*str="Clanguage!"; /*定義字符指針變量str并初始化*/此時,字符指針指向的是一個字符串常量的首地址,即指向字符串的首地址。
8.3指針與數(shù)組8.3.2
指針與字符串【例8-10】有字符串a(chǎn)和b,編寫程序,使用指針將字符串b連接到字符串a(chǎn)的后面?!締栴}分析】本題可以定義兩個指針變量str1和str2,分別指向數(shù)組a和b的第一個元素,然后移動指針str1到數(shù)組a的結(jié)束符處,接著將str2連接到str1的后面即可。
8.3指針與數(shù)組8.3.2
指針與字符串【參考代碼】#include<stdio.h>intmain(){ chara[50],b[30]; /*定義兩個字符數(shù)組a和b*/ char*str1,*str2; /*定義兩個指針變量*/ printf("Enterstring1:"); gets(a); /*輸入字符數(shù)組a*/ printf("Enterstring2:"); gets(b); /*輸入字符數(shù)組b*/
8.3指針與數(shù)組8.3.2
指針與字符串 str1=a; /*指針變量str1指向數(shù)組a的第一個元素*/ str2=b; /*指針變量str2指向數(shù)組b的第一個元素*/ while(*str1!='\0') str1++; /*找到數(shù)組a的結(jié)束標(biāo)記*/ while(*str1++=*str2++); /*將str2連接到str1的后面*/ printf("a+b=%s\n",a); /*輸出連接后的數(shù)組a*/}
8.3指針與數(shù)組8.3.2
指針與字符串【運行結(jié)果】程序運行結(jié)果如圖所示。
名師點睛這里要注意字符指針與字符數(shù)組之間的區(qū)別。例如,有下面語句:char*str="Clanguage!";charstring[30]="Thisisastring.";str是一個變量,可以改變str使它指向不同的字符串,但不能改變str所指向的字符串常量的值。string是一個數(shù)組,可以改變數(shù)組中保存的內(nèi)容。
8.3指針與數(shù)組8.3.2
指針與字符串函數(shù)的參數(shù)不僅可以是一般數(shù)據(jù)類型的數(shù)據(jù)(如整型、浮點型、字符型等數(shù)據(jù)),還可以是指針類型。它的作用是將一個變量的地址傳送到另一個函數(shù)中?!纠?-11】編寫swap函數(shù)實現(xiàn)兩個變量值的交換?!締栴}分析】在第8章的例8-6中編寫過swap函數(shù),但是沒能實現(xiàn)互換主函數(shù)中兩個變量的值。原因是:C語言規(guī)定,實參對形參變量的數(shù)據(jù)傳遞是“值傳遞”,即單向傳遞,只由實參傳給形參,而不能由形參傳回給實參。因此,如果希望將交換后的值帶回到主函數(shù)中,可以利用指針作為函數(shù)參數(shù),它將一個變量的地址傳遞到被調(diào)函數(shù)中。由于指針指向的單元和變量對應(yīng)的單元相同,因此,可以在被調(diào)函數(shù)中通過指針運算符“*”實現(xiàn)對主調(diào)函數(shù)中變量值的修改。
8.4指針與函數(shù)8.4.1
指針變量作為函數(shù)參數(shù)【參考代碼】#include<stdio.h>voidswap(int*p1,int*p2) /*swap函數(shù)用于交換兩數(shù)的值*/{ intt; /*定義整型變量t*/ t=*p1; /*實現(xiàn)兩數(shù)交換*/ *p1=*p2; *p2=t;}intmain(){ inti=2,j=3; /*定義整型變量i和j并初始化*/ printf("BeforeSwap:i=%d,j=%d\n",i,j);/*輸出調(diào)用swap函數(shù)前i和j的值*/ swap(&i,&j); /*調(diào)用swap函數(shù),參數(shù)為i和j的地址*/ printf("AfterSwap:i=%d,j=%d\n",i,j); /*輸出調(diào)用swap函數(shù)后i和j的值*/ return0;}
8.4指針與函數(shù)8.4.1
指針變量作為函數(shù)參數(shù)【運行結(jié)果】程序運行結(jié)果如圖所示。
8.4指針與函數(shù)8.4.1
指針變量作為函數(shù)參數(shù)【程序說明】該程序中,swap函數(shù)的形參為指向整型的指針,調(diào)用swap函數(shù)的實參為整型變量的地址。調(diào)用swap函數(shù)后,指針變量p1中存入變量i的地址,指針變量p2中存入變量j的地址,即指針變量p1指向變量i,指針變量p2指向變量j。調(diào)用swap函數(shù),首先執(zhí)行語句“t=*p1;”,將指針p1所指的內(nèi)容存入臨時變量t中;然后執(zhí)行語句“*p1=*p2;”,將指針p2所指的內(nèi)容存入指針p1所指的變量中;最后執(zhí)行語句“*p2=t;”,將臨時變量t暫存的數(shù)據(jù)送入指針p2所指的變量中;從而完成交換兩個變量值的操作。swap函數(shù)的執(zhí)行過程和各個變量值的變化可用圖描述。
8.4指針與函數(shù)8.4.1
指針變量作為函數(shù)參數(shù)【例8-12】將例8-11的程序改寫成以下程序,試分析輸出結(jié)果。#include<stdio.h>voidswap(int*p1,int*p2){ int*t; t=p1; p1=p2; p2=t;}intmain(){ inti=2,j=3; printf("BeforeSwap:i=%d,j=%d\n",i,j); swap(&i,&j); printf("AfterSwap:i=%d,j=%d\n",i,j); return0;}
8.4指針與函數(shù)8.4.1
指針變量作為函數(shù)參數(shù)【運行結(jié)果】程序運行結(jié)果如圖所示。
8.4指針與函數(shù)8.4.1
指針變量作為函數(shù)參數(shù)【程序說明】同樣是使用指針作為形參,但是卻沒有實現(xiàn)交換變量i和j的值。原因是:在本例中語句“p1=p2;”的含義與例8-11中語句“*p1=*p2;”是不同的,它的含義是“將指針變量p2的值賦給指針變量p1”,即實現(xiàn)指針變量之間的相互賦值。swap函數(shù)的執(zhí)行過程和各個變量值的變化可用圖描述。
8.4指針與函數(shù)8.4.1
指針變量作為函數(shù)參數(shù)
高手點撥雖然C語言的函數(shù)參數(shù)都是值傳遞,但是可以通過地址間接地把被調(diào)函數(shù)的某些數(shù)值傳送給主調(diào)函數(shù)。指針參數(shù)傳遞中應(yīng)注意:形參和實參共用同一存儲單元,要從被調(diào)函數(shù)中獲得多個值,可用多個指針變量作為函數(shù)參數(shù),通過修改指針?biāo)缸兞康闹祦矸祷囟鄠€值。前面介紹了如何定義和使用指向數(shù)組的指針變量,這里介紹了指向數(shù)組的指針變量作函數(shù)參數(shù)的方法。
8.4指針與函數(shù)8.4.1
指針變量作為函數(shù)參數(shù)【例8-13】編寫程序,實現(xiàn)輸入一個字符串,調(diào)用自定義函數(shù)length()計算字符串的長度并輸出?!締栴}分析】定義函數(shù)length(),用來計算字符串的長度,在主函數(shù)中調(diào)用此函數(shù),函數(shù)的形參和實參可以用字符指針變量。
8.4指針與函數(shù)8.4.1
指針變量作為函數(shù)參數(shù)【參考代碼】#include<stdio.h>intlength(char*s) /*s為指向字符串的指針*/{ intlen=0; /*定義變量len用于存儲字符串的長度*/ while(*s!='\0') /*當(dāng)“*s!='\0'”成立時循環(huán),計算字符串長度*/ { len++; s++; }
8.4指針與函數(shù)8.4.1
指針變量作為函數(shù)參數(shù) returnlen; /*返回len的值*/}intmain(){ chara[30],*string=a; /*定義字符數(shù)組a,定義指針變量string指向a*/ printf("Pleaseinputastring:"); gets(string); /*輸入字符串*/ printf("String=%s,length=%d\n",string,length(string)); /*輸出字符串及字符串長度*/ return0;}
8.4指針與函數(shù)8.4.1
指針變量作為函數(shù)參數(shù)【運行結(jié)果】程序運行結(jié)果如圖所示?!境绦蛘f明】main函數(shù)中的string是字符指針變量,指向字符數(shù)組a的首地址。length函數(shù)的形參s是字符指針變量,在調(diào)用length函數(shù)時,將數(shù)組a的首地址傳給s,即s指向字符串的第一個字符a[0]。在while循環(huán)中,先檢查s當(dāng)前所指向的字符是否為'\0',如果不是就讓長度加1,s指向下一個元素,如此循環(huán),直到s指向字符'\0'為止,返回的len值即為字符串長度。
8.4指針與函數(shù)8.4.1
指針變量作為函數(shù)參數(shù)一個函數(shù)可以返回一個基本類型的值,也可以返回一個指針類型的數(shù)據(jù),即地址。當(dāng)將地址作為函數(shù)返回值時,該函數(shù)被稱為指針函數(shù)。其定義形式為:數(shù)據(jù)類型*函數(shù)名(形參表){ 函數(shù)體;}其中,函數(shù)名前面的“*”表示該函數(shù)為指針型函數(shù),即返回值類型為指針,數(shù)據(jù)類型表明指針指向的類型。因此,函數(shù)的返回值是一個指向該數(shù)據(jù)類型的指針?!纠?-14】使用指針函數(shù)求兩個變量的最大值。【例8-15】使用指針函數(shù)實現(xiàn)求兩個變量的最大值,返回指向較大值的指針變量,輸出指針變量指向的變量的值?!締栴}分析】
8.4
溫馨提示
- 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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 兒童骨折術(shù)后康復(fù)訓(xùn)練指南
- 兒童衛(wèi)生健康科普
- 2026年中共濰坊市委外事工作委員會辦公室所屬事業(yè)單位公開招聘工作人員備考題庫及參考答案詳解
- 2026年中國建筑科學(xué)研究院天津分院招聘備考題庫及一套完整答案詳解
- 2026年中糧家佳康(江蘇)有限公司東臺分公司招聘備考題庫有答案詳解
- 2026年【招聘備考題庫】黑龍江省生態(tài)環(huán)保集團有限公司面向社會公開招聘管理人員備考題庫完整參考答案詳解
- 2026年北京體育大學(xué)醫(yī)院(社區(qū)衛(wèi)生服務(wù)中心)合同制人員公開招聘備考題庫附答案詳解
- 2026年中遠(yuǎn)海運物流供應(yīng)鏈有限公司西南分公司招聘綜合管理崗、安全管理專員、財務(wù)專員等崗位備考題庫及一套答案詳解
- 2026年宜春市人力資源服務(wù)有限責(zé)任公司招聘備考題庫(宜春海關(guān))及1套完整答案詳解
- 2026年關(guān)于為淄博市檢察機關(guān)公開招聘聘用制書記員的備考題庫及1套完整答案詳解
- 畜牧技術(shù)員安全培訓(xùn)效果測試考核試卷含答案
- 2026年湖南郵電職業(yè)技術(shù)學(xué)院單招職業(yè)技能考試參考題庫附答案詳解
- 小學(xué)三年級語文上冊期末復(fù)習(xí)知識點總結(jié)課件
- 2026年Q1電商店鋪運營非遺文化商品上架調(diào)研
- 2025-2026學(xué)年北師大版高二數(shù)學(xué)上學(xué)期期末??碱}之隨機事件的條件概率
- 2026年小學(xué)一二年級第一學(xué)期無紙筆化考核方案及測試題(一二年級語文數(shù)學(xué))
- 2025四川金融控股集團有限公司招聘16人筆試參考題庫附帶答案詳解(3卷合一)
- 2025年人文常識競賽題庫及答案
- 2025年時事政治試題庫完整參考詳解(完整版)及答案
- 學(xué)校副校長中層干部和群團組織負(fù)責(zé)人績效考核實施細(xì)則
- GB/T 6579-2007實驗室玻璃儀器熱沖擊和熱沖擊強度試驗方法
評論
0/150
提交評論