指针详解
【1】指針包括哪些內容?
指針是一個特殊的變量,它所存儲的數值被解釋為內存的一個地址。
要了解一個指針需要搞清其四方面的內容:
(1)指針的類型
(2)指針所指向的類型
(3)指針的值 或者 指針所指向的內存區
(4)指針本身所占據的內存區
先聲明幾個指針作為例子:代碼如下:
1 int *ptr; 2 char *ptr; 3 int **ptr; 4 int (*ptr) [3]; 5 int * (*ptr) [4];【2】指針的類型怎么分析?
從語法的角度看,你只要把指針聲明語句里的指針名字去掉,剩下的部分就是這個指針的類型。
這是指針本身所具有的類型。讓我們看看例一中各個指針的類型:
1 int *ptr; //指針的類型為int* 2 char *ptr; //指針的類型為char* 3 int **ptr; //指針的類型為int** 4 int (*ptr) [3]; //指針的類型為int(*)[3] 5 int * (*ptr) [4]; //指針的類型為int*(*)[4]【3】指針所指向的類型怎么分析?
當你通過指針來訪問指針所指向的內存區時,指針所指向的類型決定了編譯器將把那片內存區里的內容當做什么來看待。
這句話很關鍵,多讀幾遍........
從語法上看,你只須把指針聲明語句中的指針名字和名字左邊的指針聲明符*去掉,剩下的就是指針所指向的類型。
下面我們看看各個指針所指向的類型:
1 int *ptr; //指針的類型為int 2 char *ptr; //指針的類型為char 3 int **ptr; //指針的類型為int* 4 int (*ptr) [3]; //指針的類型為int()[3] 5 int * (*ptr) [4]; //指針的類型為int*()[4]在指針的算術運算中,指針所指向的類型有很大的作用。
指針的類型(即指針本身的類型)和指針所指向的類型是兩個概念。
當你對C 越來越熟悉時,你會發現,把與指針攪和在一起的"類型"這個概念分成"指針的類型"和"指針所指向的類型"兩個概念,
是精通指針的關鍵點之一。
不少書就把指針的這兩個概念攪在一起了。所以越看越糊涂。
【4】指針的值----或者叫指針所指向的內存區或地址怎么分析?
指針的值即就是指針本身存儲的數值,這個值將被編譯器當作一個地址,而不是一個一般的數值。
在32 位程序里,所有類型的指針的值都是一個32 位整數,因為32 位程序里內存地址全都是32 位長。
指針所指向的內存區就是從指針的值所代表的那個內存地址開始,長度為sizeof(指針所指向的類型)的一片內存區。
以后,我們說一個指針的值是XX,就相當于說該指針指向了以XX 為首地址的一片內存區域;
我們說一個指針指向了某塊內存區域,就相當于說該指針的值是這塊內存區域的首地址。
指針所指向的內存區和指針所指向的類型是兩個完全不同的概念。
在例一中,指針所指向的類型已經有了,但由于指針還未初始化,所以它所指向的內存區是不存在的,或者說是無意義的。
以后,每遇到一個指針,都應該問問:
這個指針的類型是什么?
指針指向的類型是什么?
該指針指向了哪里?(重點注意)
【5】指針本身所占據的內存區如何分析?
指針本身占了多大的內存?你只要用函數sizeof(指針的類型)測一下就知道了。
在32 位平臺里,指針本身占據了4 個字節的長度。
指針本身占據的內存這個概念在判斷一個指針表達式是否是左值時很有用。
【6】與指針相關的運算符有哪兩個?
& 取地址運算符
* 間接運算符
&a 的運算結果也就是取變量a的地址,即就是獲取變量a的指針。
指針的類型是a 的類型再加個*。
指針所指向的數據類型是變量a的類型。
指針的值 即就是指針所指向的地址,也就是變量a的地址。
*p 的運算結果就依情況而定了??傊?p的結果是p 所指向的那個玩意。
這個東西具備這些特點:它的類型是p 指向的類型,它所占用的地址是p所指向的地址。
【7】指針類型轉換如何實現?
當我們初始化一個指針或給一個指針賦值時,賦值號的左邊是一個指針,賦值號的右邊是一個指針表達式。
在我們前面所舉的例子中,絕大多數情況下,指針的類型和指針表達式的類型是一樣的,指針所指向的類型和指針表達式所指向的類型是一樣的。
示例如下:
1 float f = 12.3; 2 float *fptr = &f; 3 int *p;在上面的例子中,假如我們想讓指針p 指向實數f,應該怎么辦?是用下面的語句嗎?示例如下:
1 int *p; 2 p = &f;不對。
因為指針p 的類型是int *,它指向的類型是int。表達式&f 的結果是一個指針,指針的類型是float *,它指向的類型是float。兩者不一致。
直接賦值的方法是不行的。至少在我的MSVC++6.0上,對指針的賦值語句要求賦值號兩邊的類型一致,所指向的類型也一致。
其它的編譯器上我沒試過,大家可以試試。為了實現我們的目的,需要進行"強制類型轉換":示例如下:
1 p =(int *) &f;如果有一個指針p,我們需要把它的類型和所指向的類型改為TYEP * 和? TYPE,那么語法格式是: (TYPE *)p。
這樣強制類型轉換的結果是一個新指針,該新指針的類型是TYPE *,它指向的類型是TYPE,它指向的地址就是原指針指向的地址。
切記一點:而原來的指針p的一切屬性都沒有被修改。
一個函數如果使用了指針作為形參,那么在函數調用語句的實參和形參的結合過程中,必須保證類型一致,否則需要強制轉換。
我們已經知道,指針的值就是指針指向的地址,在32 位程序中,指針的值其實是一個32 位整數。
那可不可以把一個整數當作指針的值直接賦給指針呢?就象下面的語句:
1 unsigned int a; 2 TYPE *ptr; //TYPE 是int,char 或結構類型等等類型。 3 a = 20345686; 4 ptr = 20345686; //我們的目的是要使指針ptr 指向地址20345686 5 ptr=a; //我們的目的是要使指針ptr 指向地址20345686 6 //編譯一下吧。結果發現后面兩條語句全是錯的。那么我們的目的就不能 7 //達到了嗎?不,還有辦法: 8 unsigned int a; 9 TYPE *ptr; //TYPE 是int,char 或結構類型等等類型。 10 a = N; //N 必須代表一個合法的地址; 11 ptr=(TYPE*)a; //呵呵,這就可以了。嚴格說來這里的(TYPE *)和指針類型轉換中的(TYPE *)還不一樣。這里的(TYPE*)的意思是把無符號整數a 的值當作一個地址來看待。
上面強調了a 的值必須代表一個合法的地址,否則的話,在你使用ptr 的時候,就會出現非法操作錯誤。
試想能不能反過來,把指針指向的地址即指針的值當作一個整數取出來。完全可以。
下面的例子演示了把一個指針的值當作一個整數取出來,然后再把這個整數當作一個地址賦給一個指針:
1 int a = 123,b; 2 int *ptr = &a; 3 char *str; 4 b = (int)ptr; //把指針ptr的值當作一個整數取出來。 5 str = (char*)b; //把這個整數的值當作一個地址賦給指針str。現在我們已經知道了,可以把指針的值當作一個整數取出來,也可以把一個整數值當作地址賦給一個指針。
?
Good? Good? Study, Day? Day? Up.
順序? 選擇? 循環? 總結
?
轉載于:https://www.cnblogs.com/Braveliu/archive/2012/12/31/2840925.html
總結
- 上一篇: IE6兼容技巧
- 下一篇: CodeSmith连接mysql