黃寶貴 禹中元
摘要:指針是C語言的特色,也是C語言的靈魂與精華,熟練使用指針可以提高編程效率。指針與數(shù)組具有密切的關(guān)系,使用指針訪問數(shù)組可以優(yōu)化程序代碼,提高程序的執(zhí)行效率。但是,由于二維數(shù)組結(jié)構(gòu)復(fù)雜,初學(xué)者難以理解其中的概念,指針與二維數(shù)組之間的關(guān)系比較模糊,增加了使用指針訪問二維數(shù)組元素的難度。該文結(jié)合生活中的示例深入淺出地解析指針與二維數(shù)組之間的關(guān)系,使用多種類型的指針訪問二維數(shù)組,并指出其中的難點及容易混淆之處。
關(guān)鍵詞:C語言;地址;指針;二維數(shù)組;元素訪問
中圖分類號:TP312? ? ?文獻標(biāo)識碼:A
文章編號:1009-3044(2019)19-0082-03
Abstract: Pointers are the most important characteristic and regarded as the soul and the best feature of the C programming language. The efficiency of C programs is improved significantly if pointers are good used in them. Pointers and arrays are closely related and they usually lead to more compact and efficient code. However, it is difficult to the abecedarians to understand the concept of pointers and two dimensional arrays because of their complicated structure. The obscure relationship between the point and array increases the hardness of visiting the elements of array by using pointers. The relationship between the point and array is analyzed with a simple way in this paper. The elements of a two dimensional array can be visited by several different type pointers. Moreover, some key and easily confused problems are listed in this paper.
Key words: C programming language; address; pointer; two dimensional array; element visited
1 背景
教授我們C語言的老師曾經(jīng)說過:沒有真正掌握指針的使用,就不能說已經(jīng)學(xué)好C語言!由此可見指針在C語言中的重要地位。事實上,指針是C語言最重要的特色,是C語言的精華。指針概念繁多,使用非常靈活,這也導(dǎo)致我們在初學(xué)C語言時難以掌握其概念及使用方法。指針與數(shù)組具有密切的關(guān)系,指針通常與數(shù)組放在一起討論與學(xué)習(xí)[1]。任何使用數(shù)組下標(biāo)訪問的表達式都可以使用指針來代替。但是,由于二維數(shù)組結(jié)構(gòu)相對復(fù)雜,加之指針的靈活多變性,用指針訪問二維數(shù)組的元素有多種方法,是我們學(xué)習(xí)的難點。下面,結(jié)合我們體育課上同學(xué)們站隊的情形,詳細討論用一級指針,二級指針,指向一維數(shù)組的指針及指針數(shù)組來訪問二維數(shù)組元素的具體操作過程。
我們班有20名同學(xué),每一位同學(xué)都有一個編號,用整數(shù)[i]表示,[i∈[0,19]]。我是體育委員,我的編號是0。站隊時,每5位同學(xué)站成一排,一共站4排。因為數(shù)組下標(biāo)從0開始計數(shù),為了后續(xù)敘述方便,我們規(guī)定最前面一排稱為第0排,往后分別是第1排,第2排,第3排。第0排的同學(xué)的編號從左到右分別是[0,1,2,3,4];第1排的同學(xué)的編號從左到右分別是[5,6,7,8,9];……,依次類推。每一排的第一位同學(xué)所在的位置稱為這排同學(xué)站隊的地址,其后的同學(xué)的地址由排頭同學(xué)的地址決定。我是體育委員,我所站立的位置決定了我們班所有同學(xué)站隊的地址。假設(shè)張三同學(xué)編號是13,他站在第2排第3個位置。那么,體育老師要想找到張三同學(xué),該怎么做呢?
以上問題用二維數(shù)組建立一個如下數(shù)學(xué)模型。二維數(shù)組a[4][5],a[0][0]=0,a[0][1]=1,…,a[0][4]=4,a[1][0]=5,…,a[1][4]=9,…,a[2][3]=13,…,a[3][4]=19。數(shù)組a可用二維表1表示。事實上,根據(jù)數(shù)組在計算機內(nèi)存中的表示方法,這20個元素在計算機內(nèi)存中按先行后列的方式進行存儲[2]。
2 用指向整型的指針訪問
體育老師只知道我所站立的位置,他必須首先找到我的位置,因為我決定了全班同學(xué)所站隊列的位置。然后,從我開始向左依次走過每一位同學(xué),走過第0排的5位同學(xué)后再從第1排的排頭開始依次走過5位同學(xué),然后再從第2排的排頭開始依次走過3位同學(xué),這時體育老師就走到了張三同學(xué)的位置,找到了張三同學(xué)。這種情況下,體育老師每次只面對一個同學(xué),體育老師每走一步只走過一位同學(xué),而張三的前面有13位同學(xué),體育老師需要走13步才能到達張三的位置??梢园洋w育老師理解為指向某位同學(xué)的指針(指針即地址[3],是同一概念的兩種說法),老師每走過一位同學(xué),該指針值加1。那么,值13又是怎么得到的呢?a[2][3]元素在第2行,第3列(再次注意到,從0開始計數(shù))。它的前面還有2個整行(第0行和第1行),每行有5個元素。而張三所在的行上,a[2][3]之前還有3個元素。所以a[2][3]之前總共有2*5+3=13個元素。用C語言描述如下。其中,(1):表示代碼的行標(biāo)。下同。
(1):int *p;? ?//p是指向int型數(shù)據(jù)的指針
(2):p = &a[0][0];? //指針p賦值為a[0][0]的地址,即p指向元素a[0][0]
(3):p = p + (2*5+3);? //p指針右移13步,指向元素a[2][3]
(4):*p ;? ? //指針解引用,得到指針?biāo)赶虻膬?nèi)容,即張三的編號13
事實上,第2行代碼可以寫成:p = a[0],但不可以寫成 p = a。&a[0][0]表示元素a[0][0]的地址,即指向a[0][0]的指針。根據(jù)一維數(shù)組元素及指針的關(guān)系,如果把a[0][0]看作為b[0]的形式,則b就是a[0]。而b[0]的指針就是b+0,即b。所以,a[0][0]的指針可以理解為指針a[0]+0即a[0]。所以,第2行代碼寫成p = a[0]也是正確的。但是,如果p = a,則*p=*a,而*a=*(a+0)=a[0]。根據(jù)指針p的定義,*p應(yīng)該是指針p所指向的內(nèi)容,是個整數(shù)。但,a[0]不是整數(shù),是指針。
3 用指向一維數(shù)組的指針訪問
體育老師忽然發(fā)現(xiàn),既然已經(jīng)知道張三同學(xué)在第2排,那么不需要從第1個同學(xué)開始依次走過前13名同學(xué)。體育老師可以從第0排開始直接越過2排走到第2排的排頭位置。在這種情況下,體育老師的“眼界”變寬,他一眼能看到一排同學(xué),一排同學(xué)可看作是個一維數(shù)組。這樣,體育老師每走一步就跨過一排同學(xué)。而張三在第2排中位于下標(biāo)為3的位置。用C語言描述如下。
1):int (*p)[5]; //p是指向具有5個元素的一維數(shù)組的指針。
2):p = a;? ?//指針指向二維數(shù)組的首地址。
3):p = p + 2; //指針p指向第2行數(shù)組
4):(*p)[3];? // *p是p指向的內(nèi)容,即一維數(shù)組,而下標(biāo)為3的元素就是張三的編號
第2行代碼不能寫成:p = a[0]或者p=&a[0][0]。因為,如果p=a[0],則*p=*(a[0])。而*p是指向數(shù)組的指針,*(a[0])=*(a[0]+0)=a[0][0]是個整數(shù)。同理,p=&a[0][0]也是錯的。
4 用二維數(shù)組名作為指針訪問
體育老師生病,由我代替他上課。作為班級體育委員,我(數(shù)組名a)當(dāng)然代表的是全部同學(xué)啦。我把同學(xué)們分成4個小組,每一排作為一個小組,隊形不能亂!每一排可以看作一維數(shù)組。這樣,我們班就可以看作4個一維數(shù)組了。每一排的排頭同學(xué)直接向我負責(zé),由排頭同學(xué)幫我找到這一排中的其他同學(xué)。這樣,可以把二維數(shù)組a折分為4個一維數(shù)組[4]。如圖1所示。這4個一維數(shù)組的名字分別是a[0],a[1],a[2],a[3]。而一維數(shù)組的名字又代表數(shù)組的首地址,即a[0]是指向a[0][0]的指針。而且,a[0]+1,a[0]+2,a[0]+3和a[0]+4分別是指向元素a[0][1],a[0][2],a[0][3]和a[0][4]的指針。稱它們?yōu)榱兄羔?。顯然,a[0],a[1],a[2]和a[3]又是數(shù)組a的4個元素。數(shù)組名a是指向該數(shù)組的指針,而且a+1,a+2,a+3分別是指向元素a[1],a[2]和a[3]的指針。稱它們?yōu)樾兄羔槨?/p>
5 用指針數(shù)組訪問
體育老師不需要知道全班同學(xué)站隊的位置,只需要知道每一排的排頭位置,把這些位置記在心里,然后根據(jù)這些位置就可以找到每一排中的任意一位同學(xué)了。根據(jù)第4小節(jié)的分析,a[0],a[1],a[2]和a[3]是4個地址(指針),分別表示4行一維數(shù)組的地址??梢远x一個有4個元素的數(shù)組,每個元素值都是指針,用它存儲a[0],a[1],a[2]和a[3]的值。這種數(shù)組稱為指針數(shù)組。C語句序列如下。
(1):int *p[4]; //定義數(shù)組p,有4個元素,每個元素是指向int型的指針
(2):int i;? //定義int型變量
(3):for(i = 0; i < 4; i++) p[i] = a[i]; //把a[0],a[1],a[2]和a[3]的值存儲到數(shù)組p中
(4):*(p[2]+3); //元素a[2][3],即張三
第3行的命令不能簡寫為p=a。因為,p是指針數(shù)組的名字,而數(shù)組名是常量,不能直接進行賦值運算。
6 結(jié)束語
指針的概念繁多,定義形式有多種,不同的定義形式表達不同的含義,有些定義形式相近但意義有很大的差別。如,int (*p)[5] (數(shù)組指針,p是指向一維數(shù)組的指針)、int *p[5] (指針數(shù)組,p是由5個元素組成的數(shù)組,每個元素是指向整型數(shù)據(jù)的指針),int (*p)(float x) (函數(shù)指針,p是指向函數(shù)的指針),int *p(float x) (返回指針值的函數(shù),p是函數(shù)名)等。這些形似義異的定義使得指針的使用非常復(fù)雜,給初學(xué)者帶來極大的困難。指針及二維數(shù)組的關(guān)系密切,二維數(shù)組元素的訪問可以用指針完成。而且,有多種實現(xiàn)方法,每種方法在具體使用中有許多需要注意的問題,在學(xué)習(xí)的時候要注意其區(qū)別。
參考文獻:
[1] Kernighan B W, Ritchie D M. The C Programming Language(C程序設(shè)計語言)[M]. 2版. 徐寶文, 李志, 譯. 北京: 機械工業(yè)出版社, 2012.
[2] 張龍波. 淺析C指針和一維、二維數(shù)組之間的關(guān)系[J]. 電腦知識與技術(shù), 2017, 13(28): 71-72.
[3] 張憶文. C語言指針教學(xué)難點透析[J]. 計算機教育, 2017(1): 155-156.
[4] 譚浩強. C程序設(shè)計[M]. 4版. 北京: 清華大學(xué)出版社, 2010.
[5] 段紅義. C語言指針教學(xué)中常見錯誤分析[J]. 電腦知識與技術(shù), 2017, 13(4): 77-78.
【通聯(lián)編輯:謝媛媛】