孫道層
(德宏職業(yè)學(xué)院 云南省芒市 678400)
C語言程序中涉及的數(shù)據(jù)都存放在計(jì)算機(jī)內(nèi)存中,計(jì)算機(jī)內(nèi)存按照編號進(jìn)行尋址,根據(jù)這個(gè)編號訪問相應(yīng)的內(nèi)存數(shù)據(jù),這個(gè)編號就是訪問內(nèi)存數(shù)據(jù)的地址,這個(gè)編號或者地址就是指針[1-2]。
指針變量是指存儲的地址可以變化的變量,在計(jì)算機(jī)內(nèi)部存儲中,在計(jì)算機(jī)內(nèi)存中,同種類型的數(shù)據(jù)往往存儲在一塊連續(xù)的內(nèi)存區(qū)域,地址是常量,不能變化移動地訪問連續(xù)的內(nèi)存單元,指針變量通過指針的移動指向連續(xù)存儲區(qū)域的不同單元,表達(dá)方便明確,概念更加清晰,因此在C語言程序設(shè)計(jì)中得到廣泛的應(yīng)用[3-4]。
廣義上來理解,C語言中只要對象有地址,都可以通過指針變量關(guān)聯(lián)這個(gè)對象,例如指針變量關(guān)聯(lián)字符串常量、普通基本類型變量、結(jié)構(gòu)體類型變量,還可以關(guān)聯(lián)數(shù)組、函數(shù)、文件等對象,貫徹C語言程序設(shè)計(jì)各個(gè)章節(jié)知識點(diǎn),也在程序設(shè)計(jì)中發(fā)揮重要的作用,指針變量正確的使用能夠提高C語言程序代碼可讀性,提高程序的運(yùn)行效率,不恰當(dāng)?shù)氖褂脮?dǎo)致代碼可讀性差,影響編譯執(zhí)行效率[5]。本文通過指針變量的概念界定、指針變量關(guān)聯(lián)對象的引用及注意事項(xiàng),深入分析各類指針變量內(nèi)涵和使用場合,對學(xué)習(xí)者如何快捷系統(tǒng)全面學(xué)習(xí)指針變量具有借鑒意義,對從事面向過程C語言程序設(shè)計(jì)開發(fā)者如何正確有效使用各類指針變量提高程序代碼質(zhì)量具有實(shí)踐借鑒意義。
一級指針變量對普通基本類型變量的關(guān)聯(lián)引用形式:*指針變量名;“*”表示該變量是指向普通基本類型變量的一級指針變量。關(guān)聯(lián)基本類型變量的二級指針變量定義形式:基本類型變量說明符**指針變量名,“**”有兩層含義,一方面表示該變量名屬于二級指針變量,另一方面表示該指針變量指向的對象是基本類型變量。
例1 指針變量關(guān)聯(lián)引用基本類型變量
#include “stdio.h”
void main()
{ int c=5,*p1=&c,**p2=&p1;
printf(“c=d% *p1=d% **p2=d% ”,c,*p1,**p2);
}
其中p1為一級指針變量,c前面關(guān)鍵字是int表示c為整型變量,把變量c的內(nèi)存地址賦值給指針變量p1,p1根據(jù)存放的地址指向整型變量c,*p1與c的值是同一對象,p1=&c,*p1=c;p2是二級指針變量,指向指針的指針,p2的內(nèi)容是一級指針變量p1的地址,*p2是指向指針變量p1,**p2是指向整型變量c,p2=&p1,*p2=p1,**p2=c。關(guān)系如圖1所示。
圖1:指針變量對整型變量的引用
在C語言中字符串沒有變量,只有常量,可以通過指針變量關(guān)聯(lián)指向字符串常量,指針變量的移動來訪問移動后的指針變量指向的字符元素,指針變量關(guān)聯(lián)字符串的定義形式:
字符類型標(biāo)識符* 字符串指針變量名;
例2指針變量關(guān)聯(lián)引用字符串
#include “stdio.h”
void main()
{ char *p= “string”;
puts(p+3);
}
p是字符指針變量,并將字符串常量”string”首個(gè)元素地址賦值給p,p+3表示從首個(gè)元素開始向后推移三個(gè)元素移動后的地址,即指向‘i’這個(gè)元素,輸出的結(jié)果是“ing”。關(guān)系如圖2所示。
圖2:指針變量對字符串常量的引用
一維數(shù)組是由一個(gè)下標(biāo)從零開始排列的同類型變量組成結(jié)構(gòu)單一的集合,一維數(shù)組在計(jì)算機(jī)內(nèi)部存儲空間是一片連續(xù)的區(qū)域,把這片連續(xù)區(qū)域的首地址賦值給指針變量,就可以通過指針變量引用一維數(shù)組元素。一維數(shù)組指針變量的定義一般形式:
一維數(shù)組類型說明符*指針變量名;
指針變量關(guān)聯(lián)引用一維數(shù)組元素一般形式:
*(指針變量+表達(dá)式),表達(dá)式一般是算術(shù)表達(dá)式,在一維數(shù)組就是指元素的所在連續(xù)單元的標(biāo)號。
例3 指針變量關(guān)聯(lián)引用一維數(shù)組元素
#include “stdio.h”
void main()
{ inti,a[6]={1,2,3,4,5,6};
Int *p=a;
for(i=0;i<6;i++)
printf(“%d ”,*(p+i));
printf(“ ”);
}
定義一個(gè)指針并把數(shù)組名a賦值指針變量p,指針變量p指向數(shù)組首個(gè)元素a[0],*(p+i)表示一維數(shù)組第i個(gè)元素,也可以表示為p[i],通過for循環(huán)語句執(zhí)行6次,分別輸出數(shù)組元素的值。如圖3所示。
圖3:使用指針變量指向一維數(shù)組
二位數(shù)組由一維數(shù)組嵌套構(gòu)成的,可以將每一行看成一個(gè)一維數(shù)組,若有定義:int c[2][3],把c當(dāng)成由c[0]和c[1]兩個(gè)元素組成一維數(shù)組,c[0]和c[1]里面的元素分別又組成一個(gè)一維數(shù)組。如圖4所示。
圖4:使用指針指向二維數(shù)組
二維數(shù)組指針變量對二維數(shù)組元素的關(guān)聯(lián)引用形式:*(*(指針變量名+行表達(dá)式)+列表達(dá)式);
例4指針變量對二維數(shù)組的關(guān)聯(lián)引用
#include “stdio.h”
void main()
{ intm,n,c[2][3]={1,2,3,4,5,6};
int **q=c;
for(m=0;m<2;m++)
for(n=0;n<3;n++)
printf(“%d”,*(*(q+m)+n));
printf(“ ”);
}
*(q+m)+n表示c[m][n]元素的地址即&c[m][n],*(*(q+m)+n)表示前面相應(yīng)地址所指向的元素即c[m][n]。
定義函數(shù)就需要計(jì)算機(jī)內(nèi)部存儲區(qū)域分配相應(yīng)的存儲空間給函數(shù),并把這個(gè)已經(jīng)分配的存儲空間的地址賦值指針變量,該指針變量就指向已經(jīng)定義的函數(shù),把某一個(gè)函數(shù)的入口地址賦值給指針變量,該指針變量就可以對指向的函數(shù)進(jìn)行調(diào)用,
函數(shù)指針變量關(guān)聯(lián)引用函數(shù)的一般形式:(*指針變量名)(實(shí)參表);
例5指針變量對函數(shù)的關(guān)聯(lián)引用
#include “stdio.h”
int min(int,int);
void main()
{ int (*p) (int,int);
inta,b;
int m;
scanf(“%d,%d”,&a,&b);
p=min;
m=(*p) (a,b);
printf(“m=%d ”,m);
}
int min (intc,int d)
{ int n;
n=(c<=d)? c:d;
return (n);
}
結(jié)構(gòu)體變量定義之后,在計(jì)算機(jī)內(nèi)存中會分配一塊連續(xù)的存儲區(qū)用來存儲結(jié)構(gòu)體變量里的各個(gè)成員數(shù)據(jù),這塊連續(xù)存儲首地址就是單元首個(gè)元素的地址,也是該結(jié)構(gòu)體變量的地址,把這塊連續(xù)的存儲區(qū)域地址賦值給指針變量,指針變量就可以調(diào)用此結(jié)構(gòu)體變量成員。
聲明結(jié)構(gòu)體類型指針變量的形式:struct結(jié)構(gòu)體類型名* 結(jié)構(gòu)體指針變量名;
結(jié)構(gòu)體指針變量關(guān)聯(lián)引用結(jié)構(gòu)體變量形式:指針變量名->成員名或(*指針變量名).成員名;
例6結(jié)構(gòu)體指針變量關(guān)聯(lián)引用結(jié)構(gòu)體變量
#include <stdio.h>
struct student
{ longstudent_num;
charstudent_name[10];
charstudent_sex;
intstudent_age;
};
Void main()
{ structstudent stu = {“20131104”,“zhangsan”,‘男’,20},*p=&stu;
printf(“student_name:%s,student_age:%d ”,
(*p).student_name,p->student_age);
}
例6中,把結(jié)構(gòu)體變量stu的地址賦值給指針變量p,可以用指針變量p引用變量stu的成員,此時(shí)(*p).student_name表示引用結(jié)構(gòu)體變量stu的name成員,p->student_age表示引用結(jié)構(gòu)體變量stu的age成員。
通過文件指針將數(shù)據(jù)流與特定的文件進(jìn)行關(guān)聯(lián),文件指針是一個(gè)FILE類型的文件結(jié)構(gòu)體指針變量,指針變量可以實(shí)現(xiàn)對已經(jīng)打開的文件進(jìn)行讀寫操作,指針變量關(guān)聯(lián)文件的定義形式:FILE * 指針變量標(biāo)識符;
其中FILE必須大寫,指針變量標(biāo)識符可以自行定義,滿足C語言標(biāo)識符的命名規(guī)則即可,比如:FILE *fp;“*”表示該變量fp是一個(gè)指針變量,F(xiàn)ILE表示fp是指向文件的指針變量,通過文件指針變量fp可以對已經(jīng)打開的指定文件進(jìn)行相應(yīng)的操作。也就是通過將文件的FILE結(jié)構(gòu)體變量地址賦值給文件指針fp,則在程序中就建立了文件和文件指針間的聯(lián)系,程序就能通過該文件指針找到與它相關(guān)的文件,實(shí)現(xiàn)對文件的操作,在C語言中,凡是要對已打開的文件進(jìn)行操作,都要通過指向該文件的文件指針實(shí)現(xiàn)。
例8 指針變量關(guān)聯(lián)引用文件
#include <stdio.h>
void main()
{ charch;
FILE * fp;
fp = fopen(“E:/CFile/test.txt”, “r”);
ch = fgetc(fp);
while(ch!=EOF)
{ putchar(ch);
ch=fgetc(fp);
}
Fclose(fp);
}
文件指針變量fp指向一個(gè)已打開的文件“test.txt”,用fgetc(fp)字符讀函數(shù)從文件指針fp指向的文件讀取字符并賦值給字符變量ch,并通過while循環(huán)體語句繼續(xù)讀寫fp所指向的文件字符,文件讀取操作完成后,使用fclose函數(shù)關(guān)閉fp所指向的文件。
在C語言中只有指針變量可以存放某類數(shù)據(jù)的地址,這類數(shù)據(jù)可以是普通變量、字符串、數(shù)組、函數(shù)、結(jié)構(gòu)體變量、文件等數(shù)據(jù)類型。不同類型的指針變量存儲的值都是不同類型數(shù)據(jù)對象在計(jì)算機(jī)內(nèi)存中的地址,C語言指針變量是依據(jù)它所指向的變量對象類型不同進(jìn)行區(qū)分,不同類型的指針變量是不能進(jìn)行賦值運(yùn)算。
C語言的精髓是指針,指針變量的正確使用能夠提高C語言程序代碼的可讀性,提高程序的運(yùn)行效率,錯誤的使用指針變量會導(dǎo)致程序出錯或者是運(yùn)行效率低下,通過系統(tǒng)研究指針變量對其它對象的關(guān)聯(lián)引用,有利于學(xué)習(xí)者和開發(fā)者使用各類指針變量提高C語言程序設(shè)計(jì)代碼質(zhì)量。