陣列與指標

2021-08-29 07:38:22 字數 3593 閱讀 1331

一、陣列

陣列中的元素可以是各種簡單資料型別,如char,int等,陣列中的元素在連續的記憶體空間中順序存放。陣列名代表陣列首元素的位址,對陣列名應用位址運算子時得到的是整個陣列的位址,例如

short tell[20];

若short佔兩個位元組,則tell+1將位址值加2,而&tell+1將位址加20,因為&tell指向的是整個陣列(即20個short)的位址。

換句話說tell是個short指標,即short*。而&tell是乙個這樣的指標,它指向包含20個元素的short陣列,即short(*)[20];(注意不能丟掉括號)。

陣列在作為引數使用時陣列名退化為指標,這也是為什麼指標作為引數傳遞時經常還需要乙個長度引數的原因。注意這裡退化的意思,暗含的意思是陣列名並不完全等同與指標。如上,對tell採用運算子sizeof得到其長度是整個陣列所佔控制項,即20*2 =40位元組,而對short *p採用sizeof得到4(指標型別所佔空間,與系統有關)

二、指標

指標中存放的是位址,可以通過*操作符取得指標所指向位址存放的變數(或常量),注意:在使用*運算子之前一定要保證指標已初始化為乙個確定的適當的位址。指標變數所佔空間與系統有關,在32位系統下為4位元組,64位系統下為8位元組。

指標的真正用武之地在於,在執行階段分配未命名的記憶體以儲存值(動態記憶體分配),此情況下只能通過指標來訪問記憶體。

以字串為例比較指標和陣列的特性如下:

1 修改內容

char a = 「hello」;

a[0] = 『x』;

cout << a << endl;

char *p = 「world」; // 注意p 指向常量字串

p[0] = 『x』; // 編譯器不能發現該錯誤

cout << p << endl;

如上,字元陣列a 的容量是6 個字元,其內容為hello\0,。a 的內容可以改變。

指標p 指向常量字串「world」(位於靜態儲存區,內容world\0),常量字串的內容是不可以被修改的。從語法上看,編譯器並不覺得語句p[0]= 『x』有什麼不妥,但是該語句企圖修改常量字串的內容而導致執行錯誤。 

2內容複製與比較

不能對陣列名進行直接複製與比較。示例7-3-2 中,若想把陣列a 的內容複製給陣列b,不能用語句 b = a ,否則將產生編譯錯誤。應該用標準庫函式strcpy 進行複製。同理,比較b 和a 的內容是否相同,不能用if(b==a) 來判斷,應該用標準庫函式strcmp進行比較。

語句p = a 並不能把a 的內容複製指標p,而是把a 的位址賦給了p。要想複製a的內容,可以先用庫函式malloc 為p 申請一塊容量為strlen(a)+1 個字元的記憶體,再用strcpy 進行字串複製。同理,語句if(p==a) 比較的不是內容而是位址,應該用庫函式strcmp 來比較。

3計算記憶體容量(sizeof)

用運算子sizeof 可以計算出陣列的容量(位元組數)。例如:

char a = "hello world";

char* p = a;

sizeof(a)的值是12(注意別忘了』\0』)。指標p 指向a,但是sizeof(p)的值卻是4。這是因為sizeof(p)得到的是乙個指標變數的位元組數,相當於sizeof(char*),而不是p 所指的記憶體容量。c++/c 語言沒有辦法知道指標所指的記憶體容量,除非在申請記憶體時記住它。

注意陣列名作為引數傳遞時退化為指標,因此此時需注意對陣列名採用sizeof時會得到4,如下:

void func(char a[100])

三、陣列指標與指標陣列

陣列指標也是指標,只不過其指向的是陣列,因此陣列指標相當於二級指標(因為陣列也相當於指標)

如: int(*a)[4]:指向由4個int組成的陣列的指標(即指向指標的指標)

指標陣列就是陣列,只是陣列中的元素都是指標。如: int*a[4];4個指向int的指標組成的陣列

舉例說明如下

指標陣列:

char *cc

=; int sz=

sizeof(cc

); 此處sz為20,因為cc是乙個指標陣列,它包含5個指標,而每個指標佔4個位元組,因此cc總共佔20個位元組。

陣列指標:

int a[2][3] = , };

int(*pp)[3]=ia;//行指標,指向二維陣列的一行,中的數字表示每一行的元素個數

cout<*(*(pp+1)+1)

雖然陣列指標可以理解為二級指標,但二者也不是完全等同的。如:

int(*p1)[3]-->p1的型別是int[3], p1+1,走3個int,乙個陣列的長度

int **p2-->p2的型別是int* ,p2+1,走1個int

四、常量指標與指標常量

常量指標指向常量(const或字面常量,如「hello」),不能通過指標改變它所指向的常量的值。當然,這不妨礙將指標修改為指向其他變數。

指標常量是說指標是常量,不能修改指標,即不能讓指標指向其他值。

比較:const int*p:常量指標

int* const p:指標常量

方法:看const離誰更近則誰不能改。const int* p 離int近因此不能通過指標改常量,為常量指標。int* const p離p近,即不能改指標,為指標常量。

另外不用const時也會出現常量指標:

char *p="hello"; //這就是常量指標

p[2]=『s』;//錯誤,指標指向乙個常量,不能改變

strcat(p,"w

要想改變指標指向的字串,可按下面的方式使用:

char *p;

char ch[6]="world";

p=ch;

p[2]='h';//正確,這樣將p指向的字串改為wohld

orld");//錯誤,指標指向乙個常量,不能改變,所以指標後面不能新增東西

五、c++中的指標使用規則

c++禁止將

const的位址賦給非

const指標,如下:

const float f=1.55;

float *p=&f;//invalid

因此將常量陣列的位址賦給非常量指標也是不允許的,這樣就意味這不能將常量陣列的陣列名作為引數傳遞給使用非常量形參的函式。

如果非要用,必須使用強制型別轉換(const_cast)。另外,僅當只有一層間接關係(如指標指向基本資料型別,不能是指標)時,才可以將非const位址或指標賦給const指標。也就是說,如果資料型別本身並不是指標,則可以將const資料或非const資料的位址賦給指向const的指標,但只能將非const資料的位址賦給非const指標

在函式中盡量使用const指標做引數,理由如下:

這樣可以避免由於無意間修改資料而導致的程式設計錯誤;

使用const使得函式能夠處理const和非const實參,否則將只能接收非const資料。

指標與陣列,指標陣列 陣列指標

int a 10 print n a p,a p a,a print n a 1 p,a 1 p a 1,a 1 a做乙個指標,步長為4,指向乙個元素,a做乙個指標,步長為40,指向乙個維陣列 int b 3 4 print n b p,b p,b p b,b,b print n b 1 p,b 1...

指標陣列與陣列指標

1.指標陣列 指標陣列中每乙個元素都是乙個指標,也既是存放字串的首位址。所以指標陣列適合處理若干個長度不等的字串。定義的一般形式為 型別說明符 指標陣列名 陣列長度 例如 int p 3 宣告乙個陣列,指標陣列p,由3個int型別指標變數元素組成 從運算子的優先順序分析,由於 的優先順序大於 所以p...

指標陣列與陣列指標

呵呵,實在是厭倦了繞口的解釋。指標陣列,故名思義,就是指標的陣列,陣列的元素是指標 陣列指標,同樣,就是直想陣列的指標。簡單舉例說明 int p 2 首先宣告了乙個陣列,陣列的元素是int型的指標。int p 2 宣告了乙個指標,指向了乙個有兩個int元素的陣列。其實這兩種寫法主要是因為運算子的優先...