指針

    參考:http://www.jizhuomi.com/software/78.html

    指針是一個特殊的變量,它裏面存儲的數值被解釋成爲內存裏的一個地址。

     我們使用的內存的基本存儲單位是字節,一個字節由8個二進制位組成。每個字節都會按照一定的規則編號,這個編號就是該字節存儲單元的地址。計算機就是利用這種編號也就是字節存儲單元的地址來定位內存進行數據讀寫的。

     我們在訪問內存中的數據時,有兩種方式,一種是通過變量名,一種是通過地址。我們聲明的每個變量都是佔據內存空間的,char型佔1個字節,float型佔4個字節。而內存空間的分配是在什麼時候呢?全局變量、static靜態變量等靜態生存期變量在程序開始運行之前(編譯時)就被分配了內存空間,動態生存期的變量是在變量聲明時分配內存空間的,然後變量名也代表了分配的空間。但是有時候沒有變量名可用或者很不方便,例如,在動態內存分配時就沒有變量名可以用;調用函數傳遞很多參數時,就不可能一個一個的通過變量名傳遞,而是需要用地址傳遞。

       指針類型

    從語法的角度看,你只要把指針聲明語句裏的指針名字去掉,剩下的部分就是這個指針的類型。這是指針本身所具有的類型。

int *ptr; //指針的類型是int *  
char *ptr; //指針的類型是char *  
int **ptr; //指針的類型是 int **  
int (*ptr)[3]; //指針的類型是 int(*)[3]  
int *(*ptr)[4]; //指針的類型是 int *(*)[4]

   指針所指向的類型

   當你通過指針來訪問指針所指向的內存區時,指針所指向的類型決定了編譯器將把那片內存區裏的內容當做什麼來看待。從語法上看,你只須把指針聲明語句中的指針名字和名字左邊的指針聲明符*去掉,剩下的就是指針所指向的類型。

int *ptr; //指針所指向的類型是int  
char *ptr; //指針所指向的的類型是char  
int **ptr; //指針所指向的的類型是 int *  
int (*ptr)[3]; //指針所指向的的類型是 int()[3]  
int *(*ptr)[4]; //指針所指向的的類型是 int *()[4] 

 地址相關運算--“*”和“&”

“*”在地址運算中叫做指針運算符,表示指針指向的變量的值,是一元操作符,例如,如果p是一個int型的指針,則*p表示p指向的int型數據的值。“&”在地址運算中叫做取地址運算符,也是一個一元操作符,用來獲取一個對象的地址,例如,有一個變量i,&i就表示變量i的存儲單元地址。“*”出現在聲明語句中被聲明的變量名之前時,表示聲明的是指針,例如,int *p;。“*”出現在聲明語句的初值表達式中或者執行語句中時,表示指針指向的對象的內容,例如,int i=*p; cout<<*p;。“&”出現在聲明語句中被聲明的變量名之前時,表示聲明的是引用,例如,int &rf;。“&”出現在聲明語句的初值表達式中或者執行語句中時,表示取對象的地址

指針的賦值

 當我們聲明瞭一個指針之後,這個指針變量中沒有存儲任何確定的地址值,而是一個隨機整數。也就是它指向的地址是不確定的,有可能它指向了系統的重要數據,這時候我們如果修改了它指向地址的值可能會引起想象不到的系統問題。所以指針聲明以後要先賦值纔可以引用。

給指針賦值可以有下面兩種方法:

int a[5];         // 聲明一個整型數組
int *p1=a;     // 聲明指針p1,並用數組首地址a來初始化p1
int *p2;         // 聲明指針p2
p2=a;           // 將數組首地址a賦值給指針p2

數組名就是數組的首地址,所以可以用數組名來賦值給指針。

     賦給指針變量的值必須是地址常量(比如數組名)或地址變量,但一定不能是非0整數。給指針賦值爲0時表示該指針是一個空指針,它不指向任何地址,比如,int *p=0;。爲什麼會把指針聲明爲空指針呢?我們在聲明一個指針時沒有給它賦值,這時它是一個隨機的值,在給它賦確定的地址值之前如果我們使用了它,就可能會訪問到重要的內存地址並破壞此地址的數據,造成嚴重後果,所以我們在軟件開發中一般先將指針設爲空指針。

舉個例子:

#include <iostream>
int main(void)
{
	using namespace std;
	int *p; //聲明int型指針p
	int i=6; //聲明int型數i,賦值爲6
	p=&i; //取i的地址賦給p

	cout<<"Value: i="<<i;//輸出int型數的值
	cout<<", *p="<<*p<<endl;

	cout<<"Addresses: &i= "<<&i;//輸出i的地址
	cout<<", p: p= "<<p<<endl;//輸出p的值

	*p=*p+1;
	cout<<"Now i= "<<i<<endl; 

	return 0;
}

輸出的結果爲

    注意:int *p=&i,是初始化指針p,將其值定義爲&i,並不是初始化*p,另外給指針賦值時,並不能直接在那放個整數,例如 int*p;p=0xB8000000;這個左邊的p是一個指向int的指針,不一定是int型,可以把它賦給地址,但是右邊是一個整數,並不能代表其爲一個地址,,最好的辦法就是強制類型轉換p=(int *) 0xB8000000;

    我們可以聲明指向常量的指針,這時候指針本身的值可以改變,也就是指針可以指向其他對象,但是我們不能通過指針改變它指向的值。例如:

 const char *name="Tom"; //指向常量的指針
 char s[]="Lili";
 name=s;                               //正確,name本身的值可以改變
 *name=’a’;                           //編譯時指出錯誤,不能通過name修改指向的對象
我們還可以聲明指針常量,這時候指針本身的值不能改變,例如:

int a=1;
int b=2;
int *const p=&a;    // 聲明指針常量p
 p=&b;               // 錯誤,不能改變指針常量p的值

         我們進行指針賦值時可以將某個指針的值賦給相同類型的另一個指針。但是有一種特殊類型的指針,可以用任意類型對象的地址爲之賦值,這就是void類型指針。我們在使用void類型的指針訪問數據時需要進行強制類型轉換。舉個例子:

<span style="font-family:FangSong_GB2312;"> void *p;
 int *p1;
 int a;
 void main()
  {
       p=&a;         // void類型的指針p指向整型變量a
       p1=(int*)p;   // 用強制類型轉換的方式將void指針p的指針賦給int型指針p1
   }</span>



發佈了33 篇原創文章 · 獲贊 15 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章