目錄
1 內存空間的訪問方式
2 指針變量的聲明運算和賦值運算
2.1 指針變量的聲明
2.2 與地址有關的運算以及指針的賦值
2.3 指針的賦值
3 指針的運用
3.1 指針運算
3.2 用指針處理數組元素
3.3 指針數組
4 指針的其餘運用——函數
4.1 指針型函數
4.2 指向函數的指針ios
計算機的內存存儲器被劃分爲一個個存儲單元。儲存單元按必定的規則編號,這個編號就是存儲單元的地址。地址編碼的基本單位是字節,每一個字節由8個二進制位組成,也就是說每一個字節是一個基本內存單元,有一個地址。計算機就是經過這種編號的方式來管理內存數據讀寫的準肯定位的。數組
C++程序經過兩種方式利用內存單元存取數據:一是經過變量名,二是經過地址。例如:對於一些常見的32位的系統,short型佔2個字節,long型佔4個字節。在變量得到內存空間的同時,變量名也就成了相應的內存空間的名稱,在變量的整個生存期內均可以用這個名字訪問該內存空間。可是,有時使用變量名不夠方便或者根本沒有變量名可用時,表如今程序語句中就是須要直接用地址來訪問內存單元。函數
指針也是一種數據類型,具備指針類型的變量稱爲指針變量。指針變量是用於存放內存單元地址的。編碼
指針也是先聲明後使用,聲明指針的語法形式時:spa
數據類型 *標識符
其中」*「即是這裏聲明的是一個指針類型的變量。數據類型能夠是任意類型,指的是指針所指向的對象(包括變量和類的對象)的類型,這說明了指針所指的內存單元能夠用於存放什麼類型的數據,稱之爲指針的類型。指針
C++提供了兩個與地址相關的運算符——「*」、「&」。「**」稱爲指針運算符,也稱解析(dereference),表示獲取指針所指向的變量的值,這是一個一元操做符。「&」稱爲取地址運算符,也是一個一元運算符,用來獲得一個對象的地址。code
1)一元運算符「*」出如今聲明語句中,在被聲明的變量名以前時,表示聲明的是指針,例如:對象
int *p; //聲明p是一個int型指針
2)「*」出如今執行語句中或聲明語句的初始化表達式中做爲一元運算符時,表示訪問指針所指對象的內容,例如:內存
cout << *p; //輸入指針p所指的內容
3)「&」出如今變量聲明語句中位於被聲明的變量左邊,表示聲明的是引用,例如:io
int &rf //聲明一個intxing
4)」&「再給變量賦初值時出現阿紫等號右邊或在被執行語句中做爲一元運算符出現時,表示取對象的地址,例如:
int a,b; int *pa,*pb=&b; pa=&a;
1) 在定義指針的同時進行初始化賦值。語法形式爲:
存儲類型 數據類型 *指針名 = 初始地址;
2) 在定義以後,單獨使用賦值語句。賦值語句的語法形式爲:
指針名 = 地址
若是使用對象地址做爲指針的初值,或在賦值語句中將對象地址賦給指針變量,該對象必須在賦值以前就聲明過,並且這個對象的類型應該和指針類型一致。也可使用一個已經賦值的指針初始化另外一個指針,這就是說,可使多個指針指向同一個變量。
一個數組,能夠用它的名稱來直接表示它的起始地址。數組名稱實際上就是一個不能被賦值的指針,即指針常量。
關於指針類型還有如下方面應該注意:
1) 能夠聲明指向常量的指針,此時不能經過指針來改變所指對象的值,但指針自己能夠改變,能夠指向另外的對象。例如:
int a; const int *p1=&a; //p1是指向常量的指針 int b; p1=&b; *p1=1;
2) 使用指向常量的指針,能夠確保指針所指向的常量不被意外更改。
int * const p2=&a; p2=&b;
3) 通過使用類型顯式轉換,經過void類型的指針即可以訪問任何類型的數據。
0專用於表示空指針,也就是一個不指向任何有效地址的指針,要養成一個好的習慣,若是不便於用一個有效地址給一個指針變量賦初值,那麼應當用0做爲它的初值,從而避免指向不肯定的指針出現。
通常來說,指針的算術運算是和數組的使用密切聯繫的,由於只有在使用數組是,纔會獲得連續分佈的可操做內存空間。對指針的進行算數運算時,必定要確保運算結果所指向的地址是程序中分配使用的地址。
指針加減運算的特色使得指針特別適合於存儲在一段連續內存空間中的同類數據。二數據剛好是具備必定順序關係的若干同類型變量的集合體,數據元素的儲存在物理上也是連續的,數組名就是數組存儲的首地址。
細節 把數組做爲函數的形參,等價於把指向數組元素類型的指針做爲形參。
void f(int p[]); void f(int p[3]); void f(int *p);
設有一個int型數組啊,有10個元素。用三種方法輸出個元素。
//使用數組名和下標 #include <iostream> using namespace std; int main(){ int a[10]={1,2,3,4,5,6,7,8,9,0}; for (int i=0;i<10;i++) cout<<a[i]<<" " cout<<endl; return 0; }
//使用數組名和指針運算 #include <iostream> using namespace std; int main(){ int a[10]={1,2,3,4,5,6,7,8,9,0}; for(int i=0;i<10;i++) cout<<*(a+i)<<" "; cout<<endl; return 0; }
//使用指針變量 #include <iostream> using namespace std; int main(){ int a[10]={1,2,3,4,5,6,7,8,9,0}; for(int *p=a;p<(a+10);p++) cout<<*p<<" "; cout<<endl; return 0; }
結果都爲:
若是一個數組的每個元素都是指針變量或者是指針常量,那麼這個數組就是指針數組。
例如用指針數組輸出一個矩陣:
#include <iostream> using namespace std; int main(){ int line1[]={1,0,0}; int line2[]={0,1,0}; int line3[]={0,0,1}; int *pLine[3]= {line1,line2,line3}; cout<<"Matrix test:"<<endl; for (int i=0;i<3;i++){ for (int j=0;j<3;j++) cout<<pLine[i][j]<<" "; cout<<endl; } return 0; }
當一個函數返回值是指針類型時,這個函數就是指針型函數。使用指針型函數的最主要的目的就是要在函數結束時把大量的數據從被調函數返回到主調函數。
指針型函數的通常定義形式是:
數據類型 *函數名(參數表) { 函數體 }
每個函數都有函數名,實際上這個函數就表示函數的代碼在內存中的起始地址。由此看來,調用函數的一般形式「函數名(參數表)」的實質就是「函數代碼首地址(參數表)」。
聲明一個函數指針時,也須要說明函數的返回值,形式參數列表,其通常的語法以下:
數據類型 (*函數指針名)形參表