概述:
數組是一種資料格式,能夠存儲多個同類型的值。
一維數組可用來實作線性表的順序存儲、哈希表、堆(堆排序部分)等;
二位數組可用來儲存圖的鄰接矩陣等。
1.1 一維數組的聲明與字元數組
1.1.1 一維數組的聲明與初始化
1.一維數組的聲明
應指出以下三點:
1)存儲在每個元素中的值的類型;
2)數組名;
3)數組中的元素數,數組的元素數必須用值大于等于1的常量表達式定義。
需要引起注意的地方:數組定義中類型不能使引用,因為引用是不能指派的,而數組中元素必須可以被指派。
如下面的定義就是錯誤的。
int& a[10]; // 錯誤的
雖然沒有引用數組,但數組可以有引用。
int a[6] = {0, 2, 4, 6, 8, 10};
int (&p)[6] = a; // p是數組a的引用
注:數組的引用可以用于函數實參傳遞。此時可確定傳遞過來的數組長度合乎要求。
2.一維數組的初始化
1)函數體外定義的内置類型數組(即内置類型的全局數組),元素初始化為0;
2)函數體内定義的内置類型數組,元素無初始化(注意,若隻初始化部分元素,其後的元素此時也會被初始化為0);
3)如果不是内置類型,則不管其在哪定義,自動調用其預設構造器函數為其初始化,若該類型無預設構造函數則會報錯。
注:當數組的大小未知時,需要動态聲明一維數組,聲明格式如下:
int* a = new int[n];
//....
delete []a; // 當數組使用完畢,需要釋放記憶體空間
1.1.2 字元數組
字元數組的初始化既可以用字元常量也可以用常量字元串(末尾有空字元)記性初始化:
方式1:char ca1[] = {'C', '+', '+'}; // 末尾沒有null字元
char ca1[] = {'C', '+', '+', '\0'}; // 末尾顯示添加null字元
方式2:char ca1[] = "C++"; // 末尾自動添加null字元
注:ca1的長度為3,ca2和ca3的長度為4。
const char ch4[5] = "Hello"; // 編譯錯誤 數組長度應為6
另外,C/C++很多字元串處理函數(strcpy,strcat等),傳遞給這些标準庫函數的指針必須是非零值并且是指向以null結束的字元數組的第一個元素。
1.2 二維數組
1.2.1 二位數組的聲明與初始化
初始化方式分為兩種:
1)按行初始化:
int a[3][4] = {{0, 1, 2, 3},
{4, 5, 6, 7},
{8, 9, 10, 11}};
2)順序初始化:
int a[3][4] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
注:如果隻是初始化部分,則其餘的規則按照一維數組的初始化規則。
C++規定,在聲明和初始化一個二維數組時,如果對二維數組的所有元素都指派,則第一維(行數)可以省略,但第二維一定不能省略。
1.2.2 行優先存儲和列優先存儲
本質上講,所有數組在記憶體中都是一維線性的,C/C++中,二維數組按照行優先順序連續存儲,是以按照行優先讀取可以順序讀取,速度更快。
注:二維數組a[x][y]轉化為一維數組b:a[x][y] = b[x*列數 + y]。
1.2.3 二維數組的動态聲明
int **a = new int* [m];
for(int i = 0 ; i < m ; i++)
a[i] = new int[n];
動态聲明的數組任意的a[k]都是一個int*類型,即一個位址,是以隻能a[i][j]或者*(*(a+i)+j)來通路數組元素。
此外動态聲明的數組,使用後需要釋放記憶體。
for(int i = 0 ; i < m ; i++)
delete []a[i];
delete []a;
1.3 數組指針、指針數組、數組名的指針
1.3.1 指針運算---算數運算、關系運算
C/C++規定的合法運算包括:指針與整數的加減、同類型指針間的比較、同類型的兩個指針相減。
指針與整數的加減
當一個指針和一個整數進行算數運算的時候,整數在執行加法運算前始終會根據合适的大小進行調整,這個“合适的大小”就是指針所指向類型的大小。
例如:float占據4個位元組,在計算float型指針加3的表達式時,這個3将根據float的類型大小(即此例中的4)進行調整為12。
同類型的兩個指針相減
減法運算的值是兩個指針在記憶體中的距離(以數組元素長度為機關,不是以位元組為機關)。
同類型的兩個指針比較
進行<、<=、>、>=運算,前提是它們都指向同一個數組中的元素。根據所使用的操作符,比較表達式的值表示那個指針指向數組更靠前或靠後。
下面的代碼用于清楚一個數組中所有的元素:
float values[5];
float *vp;
vp = &values[0] ;
while(vp < &values[5]) {
*vp = 0;
*vp++; // 等價于 *vp ++= 0
}
1.3.2 指針數組與數組指針
指針數組:一個數組裡面裝着指針,即指針數組為一個數組。
例如一個有10個指針的數組,其中每個指針是指向一個整數型,那麼此數組的定義為:
int *a[10];
數組指針:一個指向數組的指針,它其實還是指針,隻不過它指向整個數組。
例如一個指向有10個整型元素數組的指針定義為:
int (*p)[10]; // 由于[]的優先級高于*,是以必須添加()
注意:二維數組的數組名是一個數組指針,若有:
int a[4][10];
int (*)p[10];
p = a; // a的類型是 int(*)[10]
對應關系如下圖:

若有如下代碼:
int a[10];
int (*p)[10] = &a; // 注意此處是&a,不是a,a的類型是int*,&a的類型是int(*)[10]
int *q = a;
對應關系如下圖:
可見,p與q雖然都指向數組的一個元素,但由于p的類型與q的類型不同,p是指向有10個元素整型數組的指針,*p的大小是40位元組,故p+1跳過40位元組;而q是指向整型的指針,*q的大小是4位元組,故q+1跳過4位元組。
1.3.3 指針在數組中的應用
指針和數組密切相關,特别是在表達式中使用數組名時,該名字會自動轉換為指向數組首元素(第0元素)的指針。
int ia[] = {0, 2, 4, 6, 8};
int *ip = ia; // 指針ip指向了數組ia的首位址
ip = &ia[4]; // ip指向了ia[4]
ip = ia; // 重新指向ip[0]
int *ip2 = ip + 4 // ip2指向ia[4]
注:對于int a[10],可以有以下幾種方式表示a[1]:
&a[0] + 1; // &a[0]等價于a,為首元素的位址
(int*)&a + 1; // &a為指向數組的指針,與a類型不同(&a類型為int(*)[10]),但指向的單元相同,強制轉化為int*,加1跳過一個int大小
(int*)((char*)&a + sizeof(int)) ; // 強制轉化為char*,加1跳過char的大小,跳了4次(int的大小), 再強制轉化為int*(指向a[1]的指針類型為int*)
&、*總結:
例如這樣的聲明 int a[4][5];
&a : 類型為 int(*)[4][5];
a+i :類型為 int(*)[5];
*(a+i) :類型為 int*;
*(*(a+i) + j) :類型為int;
*(a+i) = a[i];
*(*(a+i) + j) = *(a[i] + j) = a[i][j];
數組就暫時告一段落,最後在強調一點,在遇到指針問題的時候,首先要明确指針指向的是什麼,才能知道跳躍的長度。
不明白的可以一起交流~希望可以加深大家的了解~.~
傳回目錄 -> C/C++基礎知識概述
轉載于:https://www.cnblogs.com/TinyBobo/p/4723943.html