天天看點

[C/C++基礎--筆試突擊] 1.數組

概述: 

  數組是一種資料格式,能夠存儲多個同類型的值。

  一維數組可用來實作線性表的順序存儲、哈希表、堆(堆排序部分)等;

  二位數組可用來儲存圖的鄰接矩陣等。

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]      

 對應關系如下圖:

[C/C++基礎--筆試突擊] 1.數組

若有如下代碼:

int a[10];
int (*p)[10] = &a; // 注意此處是&a,不是a,a的類型是int*,&a的類型是int(*)[10]
int *q = a;      

對應關系如下圖:

[C/C++基礎--筆試突擊] 1.數組

可見,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