C++/C 程序中,指針和數組在不少地方可以相互替換着用,讓人產生一種錯覺,以爲兩者是等價的。
數組要麼在靜態存儲區被創建(如全局數組) ,要麼在棧上被創建。數組名對應着(而不是指向)一塊內存,其地址與容量在生命期內保持不變,只有數組的內容可以改變。指針可以隨時指向任意類型的內存塊,它的特徵是“可變” ,所以我們常用指針來操作動態內存。指針遠比數組靈活,但也更危險。
下面以字符串爲例比較指針與數組的特性:
1.修改內容
示例1中,字符數組a的容量是6個字符,其內容爲 hello\0 。a 的內容可以改變,如 a[0]=‘X’。指針p 指向常量字符串“world ” (位於靜態存儲區,內容爲 world\0) ,常量字符串的內容是不可以被修改的。從語法上看,編譯器並不覺得語句 p[0]=‘X’有什麼不妥,但是該語句企圖修改常量字符串的內容而導致運行錯誤。
示例1:
char a[] ="hello";
a[0] ='X';
cout<<a<<endl;
char *p = "world"; // 注意p指向常量字符串
p[0] = 'X'; // 編譯器不能發現該錯誤
cout<<p<<endl;
2.內容複製與比較
不能對數組名進行直接複製與比較。示例2中,若想把數組a的內容複製給數組b ,不能用語句b = a ,否則將產生編譯錯誤。應該用標準庫函數st rcpy 進行復制。
同理,比較b和a的內容是否相同,不能用 i f ( b==a) 來判斷,應該用標準庫函數st rcmp進行比較。語句p = a並不能把a的內容複製指針p ,而是把a的地址賦給了p 。要想複製 a數組的內容,可以先用庫函數mal loc 爲p申請一塊容量爲st r l en( a) +1 個字符的內存,再用strcpy進行字符串複製。同理,語句i f ( p==a) 比較的不是內容而是地址,應該用庫
函數st rcmp來比較。
示例2:
// 數組
char a[] = "hello";
char b[10];
strcpy(b,a); // 不能用b = a;
if(strcmp(b, a) == 0) // 不能用if(b == a)
// 指針
int len = strlen(a);
char *p = (char *)malloc(sizeof(char) *(len + 1));
strcpy(p,a); //不要用p = a;
if(strcm(p,a) == 0) // 不要用if(p == a)
3.計算內存容量
用運算符sizeof可以計算出數組的容量(字節數)。示例3中, si zeof ( a)的值是12 (注意別忘了’\ 0’) 。指針p指向a但是si zeof ( p)的值卻是 4 。這是因爲si zeof ( p) 得到的是一個指針變量的字節數,相當於 si zeof ( char *) ,而不是p 所指的內存容量。
注意:當數組作爲函數的參數進行傳遞時,該數組自動退化爲同類型的指針。示例3中,不論數組a 的容量是多少,sizeof(a)始終等於sizeof ( char *) 。
示例3:
char a[] = "hello world";
char *p = a;//*p是指針變量
cout<<sizeof(a)<<endl; // 12字節
cout<<sizeof(p)<<endl; // 4字節
void Func(char a[100])
{
cout<<sizeof(a)<<endl; // 4字節而不是100字節
}