指針、數組和指針算術
1.指針和數組基本等價的原因在於指針算術和C++內部處理數組的方式
2.C++將數組名解釋爲地址,而第六時候說過指針變量也是一個地址
在前面講過int *a = new int [10];,指針指向new分配的內存地址,而數組不是new出來,它有自己的標識(數組名),數組名也被解釋爲第一個元素的地址。所以可以這樣使用指針和數組
int a[3] = {0,1,2};
int *b = a; //由於數組名錶示地址,指針指向地址,沒問題,而這一句等價於 int *b = &a[0];
然後訪問數組元素就由原來的數組訪問a[0],a[1],a[2]可以對應有*b,*(b+1),*(b+2)
而需要注意的是
sizeof(a); //12,a是數組名,所有求的是整個數組的大小
sizeof(b);//4,指針的大小,指針本質是地址,四字節
再舉個例子說明指針地址+1
假如指針b的地址是2000(當然正常是十六進制,這裏爲了方便舉例),b在上面我們知道是指向int數組,int四個字節,b+1指向的地址就是2004,b+2指向的地址就是2008
3.數組的地址
數組名解釋爲地址並不是所有情況,如果你對數組名應用地址運算符&時,它就不是解釋爲地址,而真的只是一個標識。
int a[10];
cout<<a<<endl; //數組第一個元素的地址
cout<<&a<<endl;//數組第一個元素的地址
這兩個輸出值是一樣的,但是意義確是不一樣,a上面有說過相當於第一個元素的地址,相當於&a[0],是一塊4字節內存的地址,而&a是表示整個數組的地址,在這是一塊40字節內存的地址,要體現出區別可以將他們分別+1
cout<<a+1<<endl; //地址值較a加了4
cout<<&a+1<<endl; //地址值較&a加了40
a看做指針的話,是一個int指針(int*),而&a是這樣一個指針,指向包含10個元素的int數組(int (*)[10])
其實我們也碰過這樣的問題,數組名不一定會作爲地址,如sizeof(數組名)返回整個數組的長度
4.指針與字符串
4.1將數組和指針的關係擴展到C-風格字符串
char a[10] = "Hello";
cout<<a<<endl;
cout<<"Hello Word"<<endl;
數組名是第一個元素的地址,所以cout語句中的a是字符'H'的地址,然後繼續打印後面的字符,知道碰見'\0'結束。
要知道:如果給cout提供一個字符的地址,那麼cout將從這個字符開始打印,直到碰見空字符爲止。
而打印字符串常量,在C++中,字符串常量其實也是一個地址,是第一個字符的地址。在打印的時候,並沒有把整個字符串發送給cout,只是發送第一個字符的地址,如果cout就會一個個讀取,直到碰見空字符爲止。
4.2在cout和多數C++表達式中,char數組名、char指針以及用引號括起來的字符串常量被解釋爲字符串第一個字符的地址
char a = "Hello";
char *a ="Hello";
"Hello"
需要細品的是第二個,a不是char類型,而是char*類型,所以才能指向字符串。
定義一個字符串數組
char a[10][10]={"hello","world",haha"}; //可以用二維數組(還沒有講到)
char *a[10]={"hello","world",haha"};//也可以用char指針數組,每個元素都是一個char指針類型
當然定義字符串數組也可以用string,上面是基於C-風格字符串
string a[10]={"hello","world",haha"};
4.3
char a[] = {"Hello"};
char *p = a;
cout<<a<<endl; //Hello
cout<<p<<endl; //Hello
cout<<(int *)a<<endl; //地址
cout<<(int *)p<<endl; //地址
一般來說給cout提供一個指針,它打印的是地址,但如果是指針類型是char*,則cout將顯示指向的字符串,如果要顯示字符串的地址,則要對這種指針進行強制轉換,如上面int*
int a[] ={1,2,3};
int *p = a;
cout<<p<<endl; //地址
4.4經常要把字符串放到數組中,初始化數組時,請使用=運算符,否則請使用strcpy()或strncpy()