版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
1、第6章 指針,6.1 指針概念 6.2 指針變量的定義和使用6.3 指針運(yùn)算6.4 指針與數(shù)組及字符串 6.5 指針數(shù)組和多級指針,6.1 指針概念,6.1.1 變量的地址 程序一旦被執(zhí)行,則該程序的指令、常量和變量等都要存放在計算機(jī)的內(nèi)存中。計算機(jī)的內(nèi)存是以字節(jié)為單位的一片連續(xù)的存儲空間,每個字節(jié)都有一個編號,這個編號就稱為內(nèi)存的地址。注意
2、 : 存儲單元的地址和它里面存放的內(nèi)容完全是兩回事。,如果在程序中用說明語句定義了一個變量,系統(tǒng)會根據(jù)變量的數(shù)據(jù)類型給它分配一定大小的內(nèi)存空間。例如: 在一個源程序中定義了如下變量:,short a = 3; int b = 100; long int c = 8; char d = 'a';,100,1002,1006,100A,,,,,,,,,,,,,,,,,3
3、,100,1000,8,‘a(chǎn)’,系統(tǒng)給變量a分配的地址是1000,變量b分配的地址是1002,變量c分配的地址是1006變量d分配的地址是100A,得到如上圖所示的內(nèi)存示意圖。,6.1.2 指針變量 除了前面介紹的普通變量之外,還使用另外一種特殊性質(zhì)的變量,即指針變量。 指針變量是存放地址的變量。它和普通變量一樣占用一定的存儲空間。但是,它與普通變量不同之處在于,指針變
4、量的存儲空間中存放的不是普通的數(shù)據(jù),而是一個地址,例如一個變量的首地址。,設(shè)某指針變量的名字是px,同時存在另外一個名字為x的普通變量,將變量x的地址送入指針px的存儲區(qū)域,即px的內(nèi)容就是變量x的地址,如下圖所示:因此我們可以看出,訪問一個變量有兩種方法:(1)通過變量本身直接訪問,(2)通過指向該變量的指針間接訪問。,6.2 指針變量的定義和使用,6.2.1 指針變量的定義及初始化 1 . 指針變量的定義
5、 指針變量在程序中使用之前,必須進(jìn)行定義。,例如: int *px; char *name; static int *pa;,上面定義了名字為px,name和pa的三個不同類型指針。變量名由用戶命名,使用字符的起名規(guī)則與變量名相同。,指針變量的存儲類型是指針變量本身的存儲類型。它與普通變量一樣,分為:
6、 auto(可以缺省) register static extern 不同存儲類型的指針使用的存儲區(qū)域不同,這與普通變量完全相同。指針的存儲類型和指針說明的程序位置決定了指針的壽命和可見性。即指針變量也分為內(nèi)部的和外部的,全局的和局部的。,2 . 指針變量的初始化/賦初值 指針變量在定義的同時,也可以被賦予初值,
7、初始化時賦予它的初值必須是地址量:,例如: int *pa=&a;它把變量a的地址作為初值賦予了int型指針pa。,注意:從表面上看,似乎把一個初始地址量賦給了指針的目標(biāo)變量*pa。其實不然,初始化形式中*pa=&a不是一個運(yùn)算表達(dá)式,而是一個說明性語句,說明指針pa指向a的地址。,1、什么叫建立指針,2、忘記給指針變量賦值的害處!——“野指針”3、指針變
8、量使用的規(guī)則定義指針變量建立指針借助指針變量間接訪問其指向的對象,——通過給指針變量賦值來確定指向關(guān)系,下面的例子是把變量n的地址賦予指針p,并且把已經(jīng)初始化好的指針p賦給指針q: int n; int *p=&n;
9、 int *q=p; 指針變量中只能存放地址,不要將一個整型量賦給一個指針變量,下面的賦值是不合法的: int *pointer=1000;,例6.1 指針的概念#include void main(){ int a; //指針pa指向a所在內(nèi)存地址 int *pa = &a;
10、 a = 10; printf("a:%d\n",a); printf("*pa:%d\n",*pa); printf("&a:%x(HEX)\n",&a); printf("pa:%x(HEX)\n",pa); printf("&pa:%x(HEX)\n
11、",&pa);},運(yùn)行結(jié)果:a:10*pa:10&a:fff4(HEX)pa:fff4(HEX)&pa:fff2(HEX)注意: 上述輸出結(jié)果中,后三行的結(jié)果每次運(yùn)行時可能不一樣,但第一行和第二行輸出值應(yīng)該是相等的。,例 求地址量數(shù)據(jù)長度的程序#include void main( ){ // 定義字符串?dāng)?shù)組str,定義一char型指針ps指向它 char
12、str[ ] = "abcdefghi", *ps = str; // 定義int型變量i,并定義一個int型指針pi指向它 int i = 6, * pi = &i; // 定義float型變量f,定義一float型指針pf指向它 float f = 6.4f, *pf = &f; // 定義double型變量d,定義一double型指針p
13、d指向它 double d = 3.1415926, *pd = &d; printf("(1) size of string's pointer is %d \ byte = %d bits.\n", sizeof(ps), 8 * sizeof(ps));,printf("(2) size of INT's po
14、inter is %d \ bytes = %d bits.\n", sizeof(pi), 8 * sizeof(pi)); printf("(3) size of FLOAT's pointer is %d \ bytes = %d bits.\n",sizeof(pf), 8 * sizeof(p
15、f)); printf("(4) size of DOUBLE's pointer is %d \ bytes = %d bits.\n", sizeof(pd), 8 * sizeof(pd)); }該程序在Borland C++ V3.1上的運(yùn)行結(jié)果為:(1) size of string's pointer is 2 byte = 16 bits.(
16、2) size of INT's pointer is 2 bytes = 16 bits.(3) size of FLOAT's pointer is 2 bytes = 16 bits.(4) size of DOUBLE's pointer is 2 bytes = 16 bits.,3. void指針 void型指針變量:用來指向一種抽象的數(shù)據(jù)類型,但不指明它指向哪種具體的數(shù)據(jù)類型,稱為“
17、無類型指針”。 定義的方法是在該指針變量的說明語句中,用void作為數(shù)據(jù)類型說明,即:,, void * 指針變量名;,定義時數(shù)據(jù)類型指定為void型,可以將已定向的各種類型指針直接賦給void型指針;將void型指針賦給其他各種類型指針時,必須采用強(qiáng)制類型轉(zhuǎn)換,將它變成指向相應(yīng)數(shù)據(jù)類型的指針。,6.2.2 指針的使用1. 取地址運(yùn)算符&和取內(nèi)容運(yùn)算符*(1).取地址運(yùn)算符& 單目&am
18、p;是取地址運(yùn)算符,單目&運(yùn)算表達(dá)式的形式為: &操作對象,例:設(shè)變量說明為 int x; char y; double z;,則地址表達(dá)式&x,&y和&z的結(jié)果類型分別為:
19、 int*(整型指針), char*(字符型指針) double*(雙精度浮點(diǎn)型指針)。,由于數(shù)組名和常量不是左值表達(dá)式,而寄存器變量沒有存儲地址,因此數(shù)組名、常量和寄存器變量均不能做單目&的操作對象。 例:設(shè)變量說明為
20、 int i ,a [4]; register int k;則&i,&a[i],&a[0](或a)都是合法的地址表達(dá)式;它們分別為變量i,元素a[i]和a[0]的地址,其類型均為int*(整型指針)。而&k,&a 均為非法表示。,(2)指針運(yùn)算符 * 單目*是間接訪問運(yùn)算符。通過指針間接訪問指針?biāo)笇ο螅醋兞浚?/p>
21、而不是通過名字訪問變量,稱為間接訪問。間接訪問的表示形式為: * 指針,例如: char c, *pc = &c; *(&c) = 'a′; *pc = 'a′;
22、 c = 'a′;,由于初始化使pc指向了c,所以上面三個賦值表達(dá)式語句的效果相同,都是將字符數(shù)據(jù)′a′存放入變量c。,(3)單目*和 &的運(yùn)算關(guān)系 單目*和 &互為逆運(yùn)算,它們之間的運(yùn)算關(guān)系可表達(dá)為: *(& 左值表達(dá)式) 等價于 左值表達(dá)式 &(*地址表達(dá)式) 等價于 地址表達(dá)
23、式,上面兩個式子表明: 對一個左值表達(dá)式先執(zhí)行& 運(yùn)算,然后對結(jié)果執(zhí)行*運(yùn)算,則最終結(jié)果就是原來的左值表達(dá)式。反之,對一個地址表達(dá)式先執(zhí)行*運(yùn)算,然后對結(jié)果執(zhí)行&運(yùn)算,則最終結(jié)果就是原來的地址表達(dá)式。,2. 指針的正確用法 使用指針的正確方法是:(1) 必須按被間接變量的類型來定義指針變量;(2) 必須用被引用變量的地址給指針變量賦值(或用指針變量初始化方式),使指針指向確定的目標(biāo)對象
24、,然后才能使用指針來引用變量。 下面這個代碼段說明了一個極為常見的錯誤: int *p; *p = 5;沒有辦法預(yù)測5這個值存放在什么地方,也不會“創(chuàng)建”用于存儲整型值的內(nèi)存空間。,3.NULL指針 NULL指針的概念是非常有用的。它提供了一種方法,表示某個特定的指針目前并未指向任何東西。 ANSI C++標(biāo)準(zhǔn)
25、定義NULL指針,它作為指針變量的一個特殊狀態(tài),表示不指向任何東西。要使一個指針變量為NULL,可以給它賦一個零值。為了測試一個指針變量是否為NULL,可以將它和零進(jìn)行比較。NULL指針并未指向任何東西,對一個NULL指針進(jìn)行解引用操作是非法的,在對指針進(jìn)行解引用操作之前,首先必須確保它并非NULL指針。,6.3 指針運(yùn)算,由于指針是持有地址的變量這一特性,指針的運(yùn)算與某些普通變量的運(yùn)算在種類上和意義上都是不同的。指針
26、運(yùn)算的種類是有限的,它只能進(jìn)行: 算術(shù)運(yùn)算 關(guān)系運(yùn)算 賦值運(yùn)算,6.3.1 指針的算術(shù)運(yùn)算 按C語言地址計算規(guī)則進(jìn)行,這種運(yùn)算與指針指向的數(shù)據(jù)類型有
27、密切關(guān)系,也就是C語言的地址計算與地址空間中存放的數(shù)據(jù)的數(shù)據(jù)類型有關(guān)。 設(shè)p1和p2是指向具有相同數(shù)據(jù)類型的一組若干數(shù)據(jù)的指針,n是整數(shù),則指針可以進(jìn)行的算術(shù)運(yùn)算有如下幾種: p1+n, p1-n, p1++, ++p1, p1--, --p1, p1-p2,1. 指針與整數(shù)的加減運(yùn)算 指針作為地址加上或減去一個整數(shù)n, 其意義是指針當(dāng)前指向位置的前方或后方第n個數(shù)據(jù)的位置。由于指針可以指向不同數(shù)據(jù)類
28、型,即數(shù)據(jù)長度不同的數(shù)據(jù),所以這種運(yùn)算的結(jié)果值取決于指針指向的數(shù)據(jù)類型。下圖所示的是不同數(shù)據(jù)類型的兩個指針實行加減整數(shù)運(yùn)算的示意圖。,,各種指針變量進(jìn)行加1運(yùn)算后的地址變化量,2. 指針加一、減一運(yùn)算 指針++、--單項運(yùn)算也是地址計算,它具有上述的計算特點(diǎn),指針的加一減一單項運(yùn)算是指針本身地址值的變化。指針++運(yùn)算后就指向了下一個數(shù)據(jù)的位置,--運(yùn)算后就指向上一個數(shù)據(jù)的位置。運(yùn)算后指針的址值的變化量取決于它指向的
29、數(shù)據(jù)類型。,例如,指針px指向int型(2字節(jié)長)數(shù)據(jù),py的內(nèi)容假設(shè)為地址值f000,當(dāng)執(zhí)行px++后,py的內(nèi)容加2,成為f002,它是下一個數(shù)據(jù)的地址。指針加一前后的變化如圖所示:,,指針加一減一單項運(yùn)算也分為前置運(yùn)算和后置運(yùn)算,當(dāng)它們和其它運(yùn)算出現(xiàn)在一個表達(dá)式中時,要注意它們之間的結(jié)合規(guī)則和運(yùn)算順序。例如, y= * px++; 該表達(dá)式中有三種
30、運(yùn)算: =,* 和++。*和++優(yōu)先于=。*和++屬于同級運(yùn)算,其結(jié)合規(guī)則是從右至左。所以++運(yùn)算是以進(jìn)行的。它相當(dāng)于: y= * (px++); 這里是后置運(yùn)算。因此該表達(dá)式的運(yùn)算順序是,訪問當(dāng)前值指向的目標(biāo),把目標(biāo)變量的值賦予y,然后,加一指向下一個目標(biāo)。,【例】看一個用指針運(yùn)算實現(xiàn)字符串復(fù)制函數(shù)的程序的例子:char *strcpy(char *
31、dest, char *src){ char *temp=dest; while( (*dest++=*src++)!=’\0 ’); return temp; //返回目的字符串的首地址} 這是標(biāo)準(zhǔn)函數(shù)庫中的函數(shù),函數(shù)體中使用了指針后置運(yùn)算: (*dest++=*
32、src++)!='\0‘; 它的運(yùn)算過程是把src的目標(biāo)變量的值賦予dest的目標(biāo)變量,然后判斷賦值表達(dá)式的結(jié)果值,即賦的值是否不等于‘\0’。dest和src的值使用后執(zhí)行加一運(yùn)算,分別指向下一個目標(biāo)。函數(shù)中循環(huán)體是空語句。,20070607 12節(jié)課,3. 指針的相減 設(shè)指針p1和p2是指向同一組數(shù)據(jù)類型一致的數(shù)據(jù),則p1-p2運(yùn)算的結(jié)果值是兩指針指向的地址位置之間的數(shù)據(jù)個數(shù)。由此看出,兩指針相減實質(zhì)上也是
33、地址計算。它執(zhí)行的運(yùn)算不是兩指針持有的地址值相減,而是按下列公式得出結(jié)果:,,式中(p1)和(p2)分別表示指針p1和p2的地址值,所以,兩指針相減的結(jié)果值不是地址量,而是一個整數(shù)。,例6.3 統(tǒng)計輸入字符串的字符個數(shù)#include void main(){ char s[20]; char * p; printf (“Enter a st
34、ring (less than 20 characters):\n”); scanf (“ %s”,s); p=s; //將字符指針指向字符數(shù)組的入口 while (*p!=’\0’) //逐個移動字符指針直到字符串結(jié)束 p++; printf (“The string length:%d\n”,p-s) ; } //p-s就是
35、字符串的長度,運(yùn)行結(jié)果:Enter a string (less than 20 characters):abcdefghiThe string length :9,程序運(yùn)行過程示意圖如圖所示:,6.3.2 關(guān)系運(yùn)算 兩個指向同一組類型相同數(shù)據(jù)的指針之間可以進(jìn)行各種關(guān)系運(yùn)算。兩指針之間的關(guān)系運(yùn)算表示它們指向的地址位置之間的關(guān)系。 假設(shè)數(shù)據(jù)在內(nèi)存中的存儲邏輯是由前向后。那么指向后方的指針大于指向
36、前方的指針。 對于兩指針p1和p2間的關(guān)系表達(dá)式: p1<p2若p1指向位置在p2指向位置的前方,則該表達(dá)式的結(jié)果值為1,反之為零。兩指針相等的概念是兩指針指向同一位置。 指向不同數(shù)據(jù)類型的指針之間的關(guān)系運(yùn)算是沒有意義的。指針與一般整數(shù)變量之間的關(guān)系運(yùn)算也是無意義的。 指針可以和零之間進(jìn)行等于或不等于的關(guān)系運(yùn)算,即:
37、 p==0或p!=0它們用于判斷指針p是否為一個空指針。,6.3.3 指針的賦值運(yùn)算 向指針變量賦值時,賦的值必須是地址常量或變量,不能是通整數(shù)。指針賦值運(yùn)算常見的有以下幾種形式:(1)把一個變量的地址賦予一個指向相同數(shù)據(jù)類型的指針 例如: char c, *pc;
38、 pc=&c;,(2)把一個指針的值賦予指向相同數(shù)據(jù)類型的另一個指針 例如: int *p, *q; ……. //q指向一個確定目標(biāo)p=q;,(3)把數(shù)組的地址賦予指向相同數(shù)據(jù)類型的指針 例如:
39、 char name[20], *pname; pname=name;,(4)動態(tài)內(nèi)存分配 在C語言中,對于定義的每一個變量,系統(tǒng)都自動在計算機(jī)中分配一個或多個字節(jié)單元以存放將要保存的變量值。,當(dāng)程序所要處理的某種數(shù)據(jù)無法確定其數(shù)據(jù)量時,便需
40、要在程序運(yùn)行期間動態(tài)地分配存儲空間,所以我們要在程序的運(yùn)行過程中,現(xiàn)場判斷實際數(shù)據(jù)的數(shù)據(jù)量,并分配內(nèi)存;當(dāng)處理完所要處理的數(shù)據(jù)時,再將這些內(nèi)存釋放。 為了實現(xiàn)動態(tài)存儲技術(shù),標(biāo)準(zhǔn)函數(shù)庫特設(shè)置了一對標(biāo)準(zhǔn)函數(shù),它們的原型在stdlib.h中。因此,在使用它們的程序開頭處,必須寫有: #include 它們的原型是:
41、 void * malloc(unsigned size); void free(void * ptr);,1)由malloc( )函數(shù)所分配的內(nèi)存空間放在數(shù)據(jù)區(qū)的堆 (Heap)中。如圖所示:,2) malloc( )函數(shù)有一個無符號整數(shù)型的形參size,用來指定所分配內(nèi)存空間的大?。ㄒ宰止?jié)為單位給出)。 對字
42、符串都是采用表達(dá)式“strlen(”字符串“) + 1”或 “strlen(指向字符串的指針) + 1”作為實參。其中,加1個字節(jié)是用來存放字符串的結(jié)尾符‘\0’。,3)當(dāng)malloc( )函數(shù)執(zhí)行成功時,其返回值是大小為size的內(nèi)存空間首地址,可采用地址賦值操作把它的返回值賦給一個指向相同數(shù)據(jù)類型的指針變量,這樣就生成了一個新的變量,稱為“動態(tài)變量”,該指針變量名就是動態(tài)變量名;當(dāng)它執(zhí)行失敗時將返回一個空指針。因此在使用mall
43、oc( )函數(shù)時,必須檢測其返回值不為空指針,不然可能因堆區(qū)的內(nèi)存資源耗盡而出錯。其一般格式為:,if(指針名 = (類型 * )malloc(空間大小) == NULL) { 出錯處理操作 },或簡化寫成:,if( ! (指針名 = (類型 * )malloc(空間大小)) { 出錯處理操作 },4)由于指針函數(shù)malloc( )的返回值是無類型指針(void * 型),把void型指針賦給其他各種非void型指針時,還必須用強(qiáng)制
44、類型轉(zhuǎn)換,把它的數(shù)據(jù)類型轉(zhuǎn)換成與“指針名”相同的數(shù)據(jù)類型。 5)free( )函數(shù)用來釋放由malloc( )函數(shù)在堆區(qū)中所分配的內(nèi)存空間,以便這些內(nèi)存空間成為再分配時的可用空間。6)free( )函數(shù)的形參ptr也是無類型指針,它專門用來接受malloc( )函數(shù)在堆區(qū)中所分配的內(nèi)存空間首地址,對其他地址量將不發(fā)生作用,因此,free( )函數(shù)是malloc( )函數(shù)的配對物,即在整個源程序內(nèi),它們是成對出現(xiàn)的。,例
45、6.4 使用malloc和free函數(shù)#include #include #include #include void main(){ char *str; //分配內(nèi)存,返回分配內(nèi)存的首地址,如分配失敗,退出系統(tǒng) if((str=(char*)malloc(10*sizeof(char)))==NULL) { printf(“not enoug
46、h memory to allocte bufer.\n”); exit(1); } strcpy(str,”hello”); //復(fù)制字符串 printf(“string is \”%s\”\n”,str); //輸出字符串 free(str); //釋放由malloc分
47、配的內(nèi)存},該程序的運(yùn)行結(jié)果為:string is “hello”,6.4 指針與數(shù)組及字符串,6.4.1 指針與數(shù)組 C語言中,指針和數(shù)組之間的關(guān)系十分密切,它們都可以處理內(nèi)存中連續(xù)存放的一系列數(shù)據(jù),數(shù)組與指針在訪問內(nèi)存時采用統(tǒng)一的地址計算方法。但是兩者之間又有本質(zhì)的區(qū)別。 數(shù)組是相同數(shù)據(jù)類型的數(shù)據(jù)集合、數(shù)組用其下標(biāo)變化實行對內(nèi)存中的數(shù)組元素進(jìn)行處理。 例如,
48、程序中說明了一個數(shù)組:int a[10]; 編譯系統(tǒng)在一定的內(nèi)存區(qū)域為該數(shù)組分配了存放int型(2字節(jié))數(shù)據(jù)的10個連續(xù)存儲空間,它們分別是a[0], a[1],······,a[9]。用a[i]表示從數(shù)組存儲首地址開始的第i個元素變量。,20070608 12jieke,20070609 78jieke,若程序中同時說明了一個int型指針:
49、 int *pa;并且通過指針賦值運(yùn)算: pa=a; 或pa=&a[0];指針pa就指向了數(shù)組a的首地址。這時指針的目標(biāo)變量*pa就是a[0]。 *(pa+1)就是a[1], *(pa+2)就是a[2] ······*(pa+i)就是a[i],如下圖所示:,例6.
50、5 指針與數(shù)組的關(guān)系#include void main(){ int a[10], *pa, i; // 數(shù)組元素賦值 for (i = 0; i < 10; i++) a[i] = i + 1; pa = a;
51、 // 將指針指向數(shù)組的首地址 for (i = 0; <10; i++) printf("*(pa+%d):%d\n", i, *(pa + i)); // 用指針的形式逐個輸出數(shù)組元素//內(nèi)容},運(yùn)行結(jié)果:* (pa+0):1* (pa+1):2* (pa+2):3* (pa+3):4* (pa+4):5* (pa+5):
52、6* (pa+6):7* (pa+7):8* (pa+8):9(pa+9):10程序中第一個for循環(huán)是把1-10賦予數(shù)組元素a[0]-a[9]。然后通過pa=a; 使指針指向數(shù)組。再用第二個for循環(huán),通過指針運(yùn)算輸出顯示數(shù)組中的據(jù)。,(1)上述表現(xiàn)形式a[i]和*(pa+i)實質(zhì)上是兩個運(yùn)算表達(dá)式,它們遵循統(tǒng)一的地址計算規(guī)則實現(xiàn)相同的功能。 (2)當(dāng)指針pa指向數(shù)組a時,就可以用a[i]、*(pa+i)、*(a
53、+i)和pa[i]等四種形式來訪問數(shù)組的元素,都是完成同樣功能的表達(dá)式。(3)在程序中它們可以互換使用,恰當(dāng)?shù)厥褂弥羔樑c數(shù)組表現(xiàn)形式的互換性,可以使程序表現(xiàn)形式更簡潔。,例6.6 指針和數(shù)組表現(xiàn)形式的互換性#include void main( ){ int i,*pa; int a[]={2,4,6,8,10}; pa=a;
54、 //將指針指向數(shù)組的首地址 for (i=0 ; i<5 ; i++) printf (”a[%d]:%d ”, i ,pa[i]); //指針采用數(shù)組的形式使用 printf (”\n”); for(i=0 ; i<5 ; i++) printf (”*(pa+%d):%d”, i ,*(a+i)); //數(shù)組采用指針的形式
55、使用 printf (”\n”);},運(yùn)行結(jié)果:a[0]:2 a[1]:4 a[2]:6 a[3]:8 a[4]:10*(pa+0):2 *(pa+1):4 *(pa+2):6 *(pa+3):8 *(pa+4):10 指針和數(shù)組在訪問地址中的數(shù)據(jù)時,其表現(xiàn)形式具有相同的意義,這是因為指針和數(shù)組名都是地址量。,特別注意: 指針和數(shù)組在訪問
56、地址中的數(shù)據(jù)時,其表現(xiàn)形式具有相同的意義,但是,指針和數(shù)組名在本質(zhì)上是不同的:指針是地址變量,而數(shù)組名是地址常量,它們在某些運(yùn)算中有著截然不同的區(qū)別 ,例如,對于指針pa和數(shù)組名a。指針可以接收賦值,其本身的值可以變化,所以它可以進(jìn)行一列運(yùn)算: pa = a;
57、 pa++, pa—;數(shù)組名參加上述運(yùn)算是錯誤的。 a[i]可以轉(zhuǎn)換成 *(pa + i)的前提是指針pa指向了數(shù)組a ,即pa指向數(shù)組a的首地址,否則不能轉(zhuǎn)換 。,6.4.2 字符指針與字符串 C語言使用char型數(shù)組處理字符串。數(shù)組中的數(shù)據(jù)可以使用相同數(shù)據(jù)類型的指針來處理,char型指針稱為字符指針。 在字符串的處理中,使用字
58、符指針比使用字符型數(shù)組有更大的便利性。(1) 在字符指針初始化時,可以直接用字符串常量作為初始值。例如, char *pa=”ABC”;(2) 在程序中也可以直接把一個字符串常量賦予一個指針。例如, char *p; p=”c program”;,例6.8 向字符指針賦予字符串程序。#include void ma
59、in( ){ //聲明一個字符指針,并初始化 char *s=”good”; char *p; while(*s!=’\0’) //采用字符的形式逐個輸出 printf(”%c”,*s++); printf(”\n”); p=”morning”; //將字符串常量賦給字符指針 while(*p!=’\0’) //采用字符的形式逐個輸出 printf(”%c”
60、,*p++); printf(”\n”);}運(yùn)行結(jié)果:goodmorning,說明: 程序中字符指針s在初始化時指向字符串”good”,而p是在程序執(zhí)行部分被賦值,指向”morning”。在兩個while循環(huán)中,分別把s和p指向的字符串逐一字符輸出。 scanf( )和printf( )函數(shù)可以使用字符指針輸入或輸出字符串。這時的轉(zhuǎn)換說明符使用%s,輸入項地址和輸出項都使用指針名。設(shè)pa是一個有確定指向的字
61、符指針,則輸入字符串時使用形式是: scanf(”%s”,pa);輸出字符串時使用形式是: printf(”%s”,pa);,6.5 指針數(shù)組和多級指針,6.5.1 指針數(shù)組 一系列有次序的指針變量集合成指針數(shù)組,為指針的集合,其每一個元素都是一個指針變量,且具有相同的存儲類型和指向相同的數(shù)據(jù)類型。指針數(shù)組的說明形式如下:,和普通數(shù)組一樣,編譯系統(tǒng)在處理指針數(shù)組說
62、明時,按照指定的存儲類型為它在內(nèi)存的相應(yīng)數(shù)據(jù)區(qū)中分配一定的存儲空間,這時指針數(shù)組名就表示該指針數(shù)組的存儲首地址。 例如,有下列的指針數(shù)組說明: int *p[2];,在程序中,指針數(shù)組可以用來處理多維數(shù)組。例如,程序中有一個二維數(shù)組,其說明如下: int
63、 a[2][3];采用降低維數(shù)的方法,這個二維數(shù)組可以分解為a[0]和a[1]兩個一維數(shù)組,它們各有3個元素。若同時存在一個指針數(shù)組: int *pa[2];它由兩個指針pa[0]和pa[1]組成,并對其進(jìn)行賦值:pa[0]=a[0];或pa[0]=&a[0][0]; pa[1]=a[1];或pa[1]=&a[1]
64、[0];,則兩個指針分別指向了兩個一維數(shù)組,這時通過兩個指針就可以對二維數(shù)組中的數(shù)據(jù)進(jìn)行處理。 如下圖:,,例6.9 用指針數(shù)組處理二維數(shù)組的數(shù)據(jù)#include void main( ){ int data[2][3], *pdata[2]; int i,j; //二維數(shù)組賦值 for (i=0 ; i<2 ; i++)
65、 for (j=0 ; j<3 ; j++) data[i][j]= (i+1) *(j+1); //將指針數(shù)組的各個元素指向降維后的 //一維數(shù)組 pdata[0]=data[0]; pdata[1]=data[1]; //采用指針數(shù)組輸出數(shù)組內(nèi)容 for ( i=0 ; i<2 ; i++) for (
66、 j=0 ; j<3 ; j++ , pdata[i]++) printf (”data[%d][%d]:%2d\n”,i,j, *pdata[i]); },運(yùn)行結(jié)果:data[0][0]:1data[0][1]:2data[0][2]:3data[1][0]:2data[1][1]:4data[1][2]:6在程序中, data[i][j] *(*(pdata+i)+j)
67、 *(data[i]+j) *(pdata[i]+j) *(*data+i)+j) pdata[i][j]是意義相同的表示方法。指針數(shù)組在說明的同時可以進(jìn)行初始化。應(yīng)該記住,不能用auto型變量的地址去初始化內(nèi)部的static型指針。,,,例6.11 字符指針數(shù)組的初始化#include void main( ){ //指針數(shù)組初始化 char * monthname[ ]=
68、 { "illegal month","January","February", "March","April", "June","July","August","September" "O
69、ctober","November","December"}; int month; //無限循環(huán),由循環(huán)體中的break語句退出循環(huán) while (1) { printf ("Enter month No.: "); scanf ("%d",&month);
70、 //輸入月份,if (month12) //月份錯誤,退出循環(huán) { printf ("Month No.%d-->%s\n",month, \ monthname [0]); break; } //打印月份對應(yīng)的英文名稱 printf ("Month No.%d-->%s\n",month, \ monthn
溫馨提示
- 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. 眾賞文庫僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
評論
0/150
提交評論