(C/C++)區別:數組與指針,指針與引用


 

1.數組跟指針的區別

數組要么在靜態存儲區被創建(如全局數組),要么在棧上被創建。數組名對應着(而不是指向)一塊內存,其地址與容量在生命期內保持不變,只有數組的內容可以改變。

指針可以隨時指向任意類型的內存塊,它的特征是“可變”,所以我們常用指針來操作動態內存。指針遠比數組靈活,但也更危險。

數組和指針特點的簡單比較:

數組 指針
保存數據 保存地址
直接訪問數據 間接訪問數據,先取得指針的內容,然后以它為地址取得數據
用於存儲數目固定且類型相同的數據 通常用於動態數據結構
編譯器自動分配和刪除 動態的分配和刪除
自身即為數據名 通常指向隱式數據

(1)指針和數組都可以在初始化的時候賦予字符串常量。盡管看上去一樣,底層機制卻不同。

指針在定義的時候,編譯器並不會為指針所指向的對象分配內存空間,它只是分配指針變量的空間。除非以一個字符串常量對其進行初始化。下面的定義創建了一個字符串常量(為其分配了內存空間) char *p = "abcd";

在ANSI C中,初始化指針時所指向的字符串被定義為只讀,如果想通過指針修改字符串的時候,會產生未定義的行為。 數組也可以用字符串常量進行初始化,但是其內容可以被修改。

(2)內容的復制和比較不能對數組進行字節復制和比較,對於兩個數組a,b,不能用b=a進行復制,而應當使用標准庫函數strcpy()。也不能使用if(b==a)進行比較,應當使用strcmp()。 而對於指針p,如果要想將數組a中的內容復制,要先申請一塊內存區域,然后使用strcpy()進行拷貝。

void main(void ) {

char a[] ="hello";

char b[10];

strcpy(b,a); // can't use b=a;
if(strcmp(b,a) == 0);//can't use if(b==a)
char *p = NULL;
p = (char *)malloc(sizeof(char )*(strlen(a)+1);
strcpy(p, a);
if(strcmp(b,a) == 0);
}
(3)計算內存容量
用運算符sizeof()可以計算出數組的容量(字節數)。如下例
char a[] = "abcdef";
char *p = a;
sizeof(a) = 7;
sizeof(p) = 4;//sizeof(p) equal to sizeof(char *) =4
注意當數組名作為函數參數進行傳遞時,該數組自動退化該類型的指針,如下例:
void TEST(char a[100])
{
cout<<sizeof(a)<<endl;// in this place, sizeof(a) is equal to sizeof(char *) = 4
}

附:數組指針與指針數組

指針數組:首先它是一個數組,數組的元素都是指針,它的元素可以指向相同類型的不同對象,數組占多少個字節由數組本身決定。它是“儲存指針的數組”的簡稱。
數組指針:首先它是一個指針,它指向一個數組。在32 位系統下永遠是占4個字節,至於它指向的數組占多少字節,不知道。它是“指向數組的指針”的簡稱。

可參考:C語言指針數組和數組指針

函數指針與指針函數

函數指針就是指向函數的存儲空間地址的指針,可以對函數指針進行賦值並且通過函數指針來調用函數,它的本質是一個指針。

而指針函數只是說明它是一個返回值為指針的函數,其本質是一個函數。

 

2.指針和引用的區別

★ 相同點:
1. 都是地址的概念;
指針指向一塊內存,它的內容是所指內存的地址;引用是某塊內存的別名。
★ 區別:
1. 指針是一個實體,而引用僅是個別名;
2. 引用使用時無需 解引用(*),指針需要解引用;
3. 引用只能在定義時被初始化一次,之后不可變;指針可變;
引用“從一而終”
4. 引用沒有 const,指針有 const,const 的指針不可變;
5. 引用不能為空,指針可以為空;
6. “sizeof 引用”得到的是所指向的變量(對象)的大小,而“sizeof 指針”得到的是指針本身(所指向的變量或對象的地址)的大小;
typeid(T) == typeid(T&) 恆為真,sizeof(T) == sizeof(T&) 恆為真,
但是當引用作為成員時,其占用空間與指針相同(沒找到標准的規定)。
7. 指針和引用的自增(++)運算意義不一樣;
 
附:C++中指針傳遞與引用傳遞
概念上
指針從本質上講就是存放變量地址的一個變量,在邏輯上是獨立的,它可以被改變,包括其所指向的地址的改變和其指向的地址中所存放的數據的改變。
而引用是一個別名,它在邏輯上不是獨立的,它的存在具有依附性,所以引用必須在一開始就被初始化,而且其引用的對象在其整個生命周期中是不能被改變的(自始至終只能依附於同一個變量)。
 
在C++中,指針和引用經常用於函數的參數傳遞,然而,指針傳遞參數和引用傳遞參數是有本質上的不同的:
指針傳遞參數本質上是值傳遞的方式,它所傳遞的是一個地址值。值傳遞過程中,被調函數的形式參數作為被調函數的 局部變量處理,即在 中開辟了內存空間以存放由主調函數放進來的實參的值,從而成為了實參的一個副本。 值傳遞的特點是被調函數對形式參數的任何操作都是作為局部變量進行,不會影響主調函數的實參變量的值。(這里是在說實參指針本身的地址值不會變)
而在引用傳遞過程中,被調函數的形式參數雖然也作為局部變量在棧中開辟了內存空間,但是這時 存放的是由主調函數放進來的實參變量的地址。被調函數對形參的任何操作都被處理成 間接尋址,即通過棧中存放的地址訪問主調函數中的實參變量。正因為如此, 被調函數對形參做的任何操作都影響了主調函數中的實參變量
 
引用傳遞和指針傳遞是不同的,雖然它們都是在被調函數棧空間上的一個局部變量,但是任何對於引用參數的處理都會通過一個間接尋址的方式操作到主調函數中的相關變量。而對於指針傳遞的參數,如果改變被調函數中的指針地址,它將影響不到主調函數的相關變量。如果想通過指針參數傳遞來改變主調函數中的相關變量,那就得使用指向指針的指針,或者指針引用。
從編譯的角度來闡述:程序在編譯時分別將指針和引用添加到符號表上,符號表上記錄的是變量名及變量所對應地址。指針變量在符號表上對應的地址值為指針變量的地址值,而引用在符號表上對應的地址值為引用對象的地址值。符號表生成后就不會再改,因此指針可以改變其指向的對象(指針變量中的值可以改),而引用對象則不能修改。
 
 
可參考文章:指針與數組的區別和聯系 
 
 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM