張龍波
(江蘇師范大學(xué)科文學(xué)院 江蘇 徐州 221116)
在討論C中普通指針與一維、二維數(shù)組的關(guān)系之前,我們的預(yù)備知識(shí)如下:
(1)一維數(shù)組a[i]中的元素a[m](m≤i-1)的地址的2種表示方法:&a[m],a+m;
(2)一維數(shù)組a[i]中的元素a[m](m≤i-1)的值的2種表示方法:a[m],*(a+m);
(3)二維數(shù)組a[i][j]的第m行第n列(m≤i-1,n≤j-1)元素a[m][n]的地址的3種表示方法:*(a+m)+n,a[m]+n,&a[m][n];
(4)二維數(shù)組a[i][j]的第m行第n列(m≤i-1,n≤j-1)元素a[m][n]的值的3種表示方法:*(*(a+m)+n),*(a[m]+n),a[m][n]。
我們已知:普通的指針變量只能指向相同數(shù)據(jù)類(lèi)型的普通變量,a[0]是整型變量,p是整型指針變量,故二者不可以使用“p=a[0]”進(jìn)行直接指向。可以采取以下兩種方法進(jìn)行指向:
(1)p=a;(數(shù)組名a代表一個(gè)指針常量,它指向第一個(gè)元素對(duì)象a[0])
(2)p=&a[0];(在整型變量a[0]的左側(cè)加“取地址運(yùn)算符”即可獲取其內(nèi)存單元格地址,故可以直接讓指針變量p指向普通變量a[0]對(duì)應(yīng)的內(nèi)存單元)
初學(xué)者容易寫(xiě)出這樣的代碼指向:p=a;(這樣寫(xiě)是錯(cuò)誤的,因?yàn)楸M管a是一個(gè)常指針(即指針常量),但是a是指向“第一個(gè)包含4個(gè)元素對(duì)象的、所謂的一維數(shù)組元素a[0]的”)。因此建議采取以下三種方法進(jìn)行指向:
(1)p=*a;(這樣寫(xiě)才正確;因?yàn)?a是對(duì)a這個(gè)常指針“取內(nèi)容”的,*a的值是a[0];因?yàn)檫@個(gè)a[0]它也是一個(gè)常指針,但是它是指向其內(nèi)部的4個(gè)元素對(duì)象的第一個(gè)元素對(duì)象a[0][0]的,即a[0]的值與&a[0][0]的值等同;所以不難得出下面的兩種方法)
(2)p=a[0];
(3)p=&a[0][0];(直接讓指針變量p去指向普通變量a[0][0])
(1)二維數(shù)組a[i][j]中,“a+m”和“&a[m]”(m≤i-1)代表的含義又是什么呢?我們發(fā)現(xiàn)它們的作用是相同的,都是用來(lái)指向二維數(shù)組a的第m行所有元素對(duì)象的;
(2)二維數(shù)組a[i][j]中,“*(a+m)+n”和“a[m]+n”(m≤i-1,n≤j-1)指向的又是什么呢?我們發(fā)現(xiàn)它們的作用也是相同的,即指向了二維數(shù)組對(duì)應(yīng)矩陣中的第m行第n列的元素對(duì)象a[m][n];
基于以上分析得出結(jié)論:使用普通指針變量指向二維數(shù)組元素a[m][n]的通用公式是:p=a[m]+n或p=*(a+m)+n或p=&a[m][n]。
(1)問(wèn)題的提出:如何定義一個(gè)指針p,將其指向具有6個(gè)元素的一維數(shù)組a呢?它們之間是如何指向及相互聯(lián)系的呢?具體探討的實(shí)例代碼行如下:
第1行:inta[6]={11,13,15,17,19,21};(定義一個(gè)包含有6個(gè)元素的一維整型數(shù)組a)
第2行:int(*p)[6];(必須定義一個(gè)數(shù)組指針,這樣才可以指向一維數(shù)組;p的類(lèi)型是:int*[6],所以p是一個(gè)專(zhuān)門(mén)指向含有6個(gè)元素的一維數(shù)組的指針變量)
第3行:p=&a;(這是可以采取的方法,作用是將數(shù)組名a所在的內(nèi)存地址賦值給數(shù)組指針p,即p指向含有6個(gè)元素的一維數(shù)組a)
第4行:printf("%p ",&a[0]);(&a[0]是用來(lái)指向a[0]這個(gè)元素對(duì)象的地址)
第5行:printf("%p ",&a);(這個(gè)結(jié)果和上一行結(jié)果一樣,但含義不同;&a是用來(lái)指向整個(gè)一維數(shù)組a的)
第6行:printf("%d ",*((*p)+3));(*p完全等價(jià)于數(shù)組名a;輸出表列“*((*p)+3)”即變成“*(a+i)”;“*(a+i)”完全等價(jià)于a[i],故打印出第4個(gè)數(shù)組元素的值17)
第7行:printf("%d ",(*p)[3]);(*p完全等價(jià)于數(shù)組名a;所以輸出表列完全等價(jià)于a[3],故打印出17)
第8行:p=p+1;(因?yàn)閜是一個(gè)“只能指向具有6個(gè)元素的一維數(shù)組的數(shù)組指針”,此行代碼的作用就是:數(shù)組指針變量p一下子完美跳過(guò)了整個(gè)的一維數(shù)組)
第9行:printf("%p ",p);(p一下子移動(dòng)了24個(gè)內(nèi)存單元格,所以打印出的內(nèi)存地址比初始地址大了18H;此行代碼等價(jià)于printf("%p ",&a+1))
(2)問(wèn)題的提出:若想定義一個(gè)指針p,需要將其指向二維數(shù)組a[3][2]的某行時(shí)(如a的第2行),需要將該指針定義成什么類(lèi)型的指針?如何指向?
a的第2行地址代表的本質(zhì)是:一個(gè)包含2個(gè)元素對(duì)象的一維數(shù)組。因此我們可以采取如下的方法:
第1行:inta[3][2]={11,13,15,17,19,21};
第2行:int(*p)[2];(定義一個(gè)數(shù)組指針變量p,這個(gè)p只能指向包含2個(gè)元素對(duì)象的一維數(shù)組)
第3行:p=a+2;(代表了p指向了二維數(shù)組a的第2行)
第4行:printf("%d ",*(*p));(打印出a[2][0]這個(gè)元素,結(jié)果為19)
第5行:printf("%d ",*(*p+1));(打印出a[2][1]這個(gè)元素,結(jié)果為21)
(3)指針變量在什么情況下可以做相加或相減的運(yùn)算?
一般情況下,相同類(lèi)型的指針變量之間只能做相減運(yùn)算,相加運(yùn)算沒(méi)有意義;同時(shí)要求這幾個(gè)指針變量必須同時(shí)指向同一數(shù)組中的元素對(duì)象的時(shí)候!如:p1和p2是完全相同類(lèi)型的指針變量,則“p2-p1”的本質(zhì)含義及結(jié)果是:“(p2-p1)/(指向的元素對(duì)象的字節(jié)數(shù))”。(注意:上方所說(shuō)的元素對(duì)象有可能是一個(gè)數(shù)據(jù),也有可能是一行數(shù)據(jù),請(qǐng)務(wù)必理解)。
(4)一維數(shù)組a的元素a[i]可以表示成*(a+i)嗎?二維數(shù)組a的元素a[i]可以表示成*(a+i)嗎?都可以。前者的*(a+i)表示a[i]這個(gè)一維數(shù)組元素的值;而后者的*(a+i)等價(jià)于*(a+i)+0;代表的是a[i][0]這個(gè)數(shù)組元素的地址。(即第i行數(shù)組元素的地址)。
(5)函數(shù)調(diào)用過(guò)程中的實(shí)參數(shù)組名和形參數(shù)組名均可以被賦值嗎?前者不可以,因?yàn)镃編譯器會(huì)把實(shí)參數(shù)組名認(rèn)識(shí)是一個(gè)常量指針,常量指針是不可以再次被賦值的;后者卻可以,因?yàn)镃編譯器會(huì)把形參數(shù)組名認(rèn)識(shí)是一個(gè)指針變量,指針變量當(dāng)然可以再次被賦值。這兩點(diǎn)請(qǐng)讀者務(wù)必注意。
(6)某二維數(shù)組a[m][n]的數(shù)組元素a[i][j]在數(shù)組中的相對(duì)位置(相對(duì)于首元素a[0][0]的地址)的計(jì)算公式是?通過(guò)對(duì)二維數(shù)組對(duì)應(yīng)矩陣數(shù)據(jù)的分析,我們不能得出a[i][j]的地址是:&a[0][0]+(i*n+j)。(n為二維數(shù)組的列數(shù))。
(1)對(duì)于一維數(shù)組a[6],&a、a和*a的區(qū)別是?
&a:這是個(gè)指針常量,它指向了整個(gè)的包含6個(gè)元素的一維數(shù)組a;
a:這也是個(gè)指針常量,它指向了一維數(shù)組a中的第1個(gè)元素a[0];(即a等價(jià)于&a[0])
*a:這是一個(gè)普通數(shù)據(jù),代表的是數(shù)組a的第一個(gè)元素a[0]的值。
(2)對(duì)于一維數(shù)組a[6],&a+1、a+1和*a+1的含義分別是?
&a+1:依然是一個(gè)指針常量,它指向了整個(gè)的一維數(shù)組a所有元素之后的下一個(gè)內(nèi)存單元格;
a+1:依然是個(gè)指針常量,它指向了一維數(shù)組a中的第2個(gè)元素a[1];
*a+1:依然是一個(gè)普通數(shù)據(jù),代表的是數(shù)組第一個(gè)元素a[0]的值再加上一個(gè)普通十進(jìn)制數(shù)字1。
(3)對(duì)于二維數(shù)組a[3][4],&a、a和*a的區(qū)別是?
&a:這是一個(gè)指針常量,它指向了整個(gè)的包含了12個(gè)元素的二維數(shù)組a;
a:這也是一個(gè)指針常量,它指向了第一個(gè)元素對(duì)象(即二維數(shù)組的第1個(gè)元素對(duì)象是一維數(shù)組a[0]),所以a是一個(gè)行指針常量,指向了二維數(shù)組的第一行(包含4個(gè)元素);
*a:依然是一個(gè)指針常量,它等價(jià)于*(a+0)+0;它指向的是“第0行第0列這個(gè)元素對(duì)象”。
(4)對(duì)于二維數(shù)組a[3][4],&a+1、a+1和*a+1的含義分別是?
&a+1:依然是一個(gè)指針常量,它指向了整個(gè)的二維數(shù)組a(包含12個(gè)元素)后邊的一個(gè)內(nèi)存單元格;
a+1:依然是一個(gè)指針常量,它指向了第2個(gè)元素對(duì)象(二維數(shù)組的第2個(gè)元素對(duì)象是一維數(shù)組a[1]),所以a+1也是一個(gè)行指針常量,指向了第2行;
*a+1:依然是一個(gè)指針常量,它等價(jià)于*(a+0)+1;它又等價(jià)于a[0]+1;所以它指向的是“第0行第1列這個(gè)元素對(duì)象”。