c/c++陣列本質論
理解陣列名
注:為方便講解,本節所說的指標的型別,指的是指標指向的型別。
1.對陣列名的簡單理解
陣列名表示的是陣列的首位址。比如一維陣列int a[11]的陣列名a就表示陣列的首位址。這裡的首位址讓人產生誤解,認為陣列名表示的是整個一維陣列的位址,其實陣列名指向的是陣列中第乙個元素位址的指標(即a指向的位址是&a[0]),表示整個陣列的位址是&a,&a表示的是乙個包含有4個元素的一維陣列的位址。雖然a和&a的位址值是相同的,但是它們的型別不一樣,a的型別是「指向int的指標」,而&a的型別是「指向乙個有11個元素的一維陣列的指標」。
2.對陣列名的理解
關鍵內容,請認真理解。
(1)對陣列名的理解,關鍵是要明白陣列名所表示的指標的型別。
(2)重點規則:陣列名是指向第乙個元素位址的指標,這個指標的型別是「指向某型別的指標」,這個指標是個常量。比如int a[4]=;,陣列名a是乙個指向第乙個元素a[0]位址的指標(即a指向的位址是&a[0]),它的型別是「指向int的指標」,這個指標是個常量,即不能改變它的值;再比如int b=1;,則a=&b;是錯誤的。
(3)對多維陣列的陣列名的理解:對於多維陣列,重點是要理解它的第乙個元素是什麼。通常講的多維陣列其實就是陣列中的陣列,即元素為陣列的陣列。因為陣列名是指向陣列中第乙個元素位址的指標,所以多維陣列的陣列名指向的也是第乙個元素位址的指標,但這個元素又是乙個陣列或多維陣列。因此對於n維陣列,陣列名是指向第乙個元素位址的指標,這個指標的型別是「指向n-1維陣列的指標」,指向的陣列有n-1維,每維有相對應的x個元素,每個元素都是某型別的(如int)。而一維陣列的陣列名的型別一般是「指向某型別的指標」。
示例: int a[3];,陣列名a指向的是第乙個元素位址&a[0]的指標,其型別是「指向int的指標」。
a[2][3];,陣列名a指向的是第乙個元素a[0]位址的指標(即a指向的位址是&a[0]),這個元素是乙個有3個元素的一維陣列,因此陣列名是乙個指向有3個元素的陣列的指標,即陣列名與指標(*p)[3]的型別相同,它的型別是「指向一維陣列的指標」。這個一維陣列有3個元素,即陣列名代表的位址是第乙個元素的位址&a[0],這與一維陣列的陣列名是相同的。
b[3][4][5]=;,陣列名b是指向第乙個元素b[0]位址的指標,即b指向的位址是&b[0]。這個元素儲存的是45的二維陣列,因此這個指標的型別是「指向二維陣列的指標」,指向的陣列有兩維,第一維有4個元素,第二維有5個元素。注意:多維陣列是陣列的陣列,三維陣列b的第乙個元素是b[0],而不是b[0][0][0]。
(4)從以上概念可以看出,多維陣列的陣列名所表示指標的型別與多維陣列的第一維的大小是沒有關係的,只與除第一維外的其他維的大小有關係,但這並不意味著第一維的大小就沒有作用了。
(5)對陣列名取址的運算:若對陣列名進行取址運算,則產生的結果是指向整個陣列的指標,即對於一維陣列名,取址後的型別是「指向一維陣列的指標」,這個陣列有x個元素;對n維陣列名取址後的型別是「指向n維陣列的指標」,這個n維陣列的每一維有x個元素。比如int a[2][3][4]=;,則&a;的型別是「指向三維陣列的指標」,這個陣列的第一維有二個元素,第2維有3個元素,第三維有4個元素。
(6)注意:早期c語言沒有「陣列的位址」這一概念,所以對陣列名取址要麼非法,要麼就等於陣列名本身。
(7)陣列名的型別相同,應滿足以下條件。
① 對於n維陣列,宣告時的元素型別要相同。
② 陣列名的型別應指向相同維數的陣列。
③ 指向的陣列的每一維的元素個數必須相同。
④ 示例:int a[2][3][4]; int b[5][3][4]; int c[2][3][5]; float d[2][3][4]
陣列名a和b:所表示的指標具有相同的型別,a和b的元素的型別相同,都是int型別。且a和b的型別都是「指向二維陣列的指標」,指向的陣列的第一維都有3個元素,第二維都有4個元素。
陣列名a和c:所表示的指標具有不相同的型別,雖然它們都是指向二維陣列的指標且元素的型別相同,但陣列名a指向的二維陣列的第二維有4個元素,而c指向的二維陣列的第二維有5個元素,即它們所指向的陣列的每一維的元素個數不相同。
陣列名a和d:具有不相同的型別,雖然它們都是指向二維陣列的指標,且每一維相對應的元素個數也相等,但a和d的元素型別不相同,a的元素型別是int,而d的元素型別是float。
3.陣列名與指標的關係
(1)對於n維陣列a,其陣列名a與&a[0],&a[0][0],&a[0][0]…[n]的位址值是相同的,也就是說,指向的是相同位址的指標。但要注意,這些指標的型別並不相同,雖然陣列名a和&a[0]型別相同,都是「指向n-1維的指標」,&a[0][0]和a[0]型別相同都是「指向n-2維的指標」,但是&a[0]和&a[0][0]型別並不一樣,因為對指標進行運算時,指標偏移多少個位元組是由其型別決定的,所以在進行運算時它們的偏移量是不一樣的。比如有二維陣列int a[2][3],假設int型別佔據4個位元組的記憶體空間,則&a[0]所指向物件的長度佔據12個位元組的記憶體空間(因為它指向的物件是具有3個元素的陣列),而&a[0][0]所指向物件的長度只佔據4個位元組的記憶體空間,對其進行算術運算時,&a[0]+1將移動12個位元組,而&a[0][0]+1則只移動4個位元組。對於n維陣列也是同樣的道理。
(2)對n維陣列的陣列名做加法運算,將使其指向n維陣列中第x個元素的位址。比如對於n維陣列a,可以使用&a[0]+1或a+1來表示指向第二個元素的位址&a[1]。
(3)對於n維陣列,直接書寫成m(04.判斷指標指向的是幾維陣列的指標
(1)對於n維陣列,若直接書寫成m(0(2)對於n維陣列,若書寫成帶有&(取址)運算子的m維陣列形式時,則指標指向的是「n-m維的指標」,或者說m維之後還有多少維就是指向多少維的指標。比如int a[2][3][4][5][6][7]=;,則&a[1][2]指向的是四維陣列(6-2)的指標,這裡a是六維陣列,即n=6,書寫時是帶取址運算子的2維陣列,因此m=2。或者說a是6維陣列,而&a[1][2]只寫了二維,二維之後還有四維,因此&a[1][2]是指向四維陣列的指標。
5.陣列名與指標的不同
(1)當陣列名作為sizeof的運算元時,返回的是整個陣列的長度,而不是指向陣列的指標的長度(在32位機器上指標的長度一般為4個位元組)。比如int a[5]=;,則sizeof(a);的結果是20(假設int型別佔4個位元組),而不是指標的長度4,因為a有5個元素,每個元素佔4個位元組;再比如int a[3][4]=;,則sizeof(a);的結果是48,即344=48。
(2)當陣列名作為&的運算元時,所產生的將是乙個「指向一維或多維陣列的指標」,而不會返回指標本身的位址。比如int a[4];,則&a;將產生乙個「指向一維陣列的指標」,這個一維陣列有4個元素。
(3)注意:陣列名雖然是乙個指標,但它與指標並不完全相同,比如陣列名作為sizeof和&的運算元時。
以上內容摘自本人所作《c++語法詳解》一書,電子工業出版社出版
繼承本質論
1.引言 關於繼承,你是否駕熟就輕,關於繼承,你是否瞭如指掌。本文不討論繼承的基本概念,我們回歸本質,從編譯器執行的角度來揭示.net繼承中的執行本源,來發現子類物件是如何實現了對父類成員與方法的繼承,以最為簡陋的示例來揭示繼承的實質,闡述繼承機制是如何被執行的,這對於更好的理解繼承,是必要且必然的...
繼承本質論
原創作品,轉貼請註明作者和出處。關於繼承,你是否駕熟就輕,關於繼承,你是否瞭如指掌。本文不討論繼承的基本概念,我們回歸本質,從編譯器執行的角度來揭示.net繼承中的執行本源,來發現子類物件是如何實現了對父類成員與方法的繼承,以最為簡陋的示例來揭示繼承的實質,闡述繼承機制是如何被執行的,這對於更好的理...
指標本質論
指標本質論 1.指標是什麼?和一般變數有什麼區別?指標就是位址,和一般變數沒有本質區別,僅僅是它有自己的規則。int a 100 int p a printf d n a 100 printf p n p 0xbfa47858 a是乙個變數名,型別是int,值是100,a有自己的位址 a p是乙個變...