第一章。指標的概念
指標是乙個特殊的變數,它裡面儲存的數值被解釋成為記憶體裡的乙個位址。要搞清乙個指標需要搞清指標的四方面的內容:指標的型別,指標所指向的型別,指標的值或者叫指標所指向的記憶體區,還有指標本身所佔據的記憶體區。讓我們分別說明。
先宣告幾個指標放著做例子:
例一:
(1)int *ptr;
(2)char *ptr;
(3)int **ptr;
(4)int (*ptr)[3];
(5)int *(*ptr)[4];
如果看不懂後幾個例子的話,請參閱我前段時間貼出的文章 < 《如何理解c和c
++的複雜型別宣告》。
1。 指標的型別。
從語法的角度看,你只要把指標宣告語句裡的指標名字去掉,剩下的部分就是這個指標的型別。這是指標本身所具有的型別。讓我們看看例一中各個指標的型別:
(1)int *ptr; //指標的型別是int *
(2)char *ptr; //指標的型別是char *
(3)int **ptr; //指標的型別是 int **
(4)int (*ptr)[3]; //指標的型別是 int(*)[3]
(5)int *(*ptr)[4]; //指標的型別是 int *(*)[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]
在指標的算術運算中,指標所指向的型別有很大的作用。
指標的型別(即指標本身的型別)和指標所指向的型別是兩個概念。當你對c越來越熟悉時,你會發現,把與指標攪和在一起的「型別」這個概念分成「指標的型別」和「指標所指向的型別」兩個概念,是精通指標的關鍵點之一。我看了不少書,發現有些寫得差的書中,就把指標的這兩個概念攪在一起了,所以看起書來前後矛盾,越看越糊塗。
3。 指標的值,或者叫指標所指向的記憶體區或位址。
指標的值是指標本身儲存的數值,這個值將被編譯器當作乙個位址,而不是乙個一般的數值。在32位程式裡,所有型別的指標的值都是乙個32位整數,因為32位程式裡記憶體位址全都是32位長。
指標所指向的記憶體區就是從指標的值所代表的那個記憶體位址開始,長度為sizeof(指標所指向的型別)的一片記憶體區。以後,我們說乙個指標的值是xx,就相當於說該指標指向了以xx為首位址的一片記憶體區域;我們說乙個指標指向了某塊記憶體區域,就相當於說該指標的值是這塊記憶體區域的首位址。
指標所指向的記憶體區和指標所指向的型別是兩個完全不同的概念。在例一中,指標所指向的型別已經有了,但由於指標還未初始化,所以它所指向的記憶體區是不存在的,或者說是無意義的。
以後,每遇到乙個指標,都應該問問:這個指標的型別是什麼?指標指向的型別是什麼?該指標指向了**?
4。 指標本身所佔據的記憶體區。
指標本身佔了多大的記憶體?你只要用函式sizeof(指標的型別)測一下就知道了。在32位平台裡,指標本身佔據了4個位元組的長度。
指標本身佔據的記憶體這個概念在判斷乙個指標表示式是否是左值時很有用。
第二章。指標的算術運算
指標可以加上或減去乙個整數。指標的這種運算的意義和通常的數值的加減運算的意義是不一樣的。例如:
例二:
1。 char a[20];
2。 int *ptr=a;
...
...
3。 ptr++;
在上例中,指標ptr的型別是int*,它指向的型別是int,它被初始化為指向整形變數a。接下來的第3句中,指標ptr被加了1,編譯器是這樣處理的:它把指標ptr的值加上了sizeof(int),在32位程式中,是被加上了4。由於位址是用位元組做單位的,故ptr所指向的位址由原來的變數a的位址向高位址方向增加了4個位元組。
由於char型別的長度是乙個位元組,所以,原來ptr是指向陣列a的第0號單元開始的四個位元組,此時指向了陣列a中從第4號單元開始的四個位元組。
我們可以用乙個指標和乙個迴圈來遍歷乙個陣列,看例子:
例三:
int array[20];
int *ptr=array;
...
//此處略去為整型陣列賦值的**。
...
for(i=0;i <20;i++)
例四:
1。 char a[20];
2。 int *ptr=a;
...
...
3。 ptr+=5;
在這個例子中,ptr被加上了5,編譯器是這樣處理的:將指標ptr的值加上5乘sizeof(int),在32位程式中就是加上了5乘4=20。由於位址的單位是位元組,故現在的ptr所指向的位址比起加5後的ptr所指向的位址來說,向高位址方向移動了20個位元組。在這個例子中,沒加5前的ptr指向陣列a的第0號單元開始的四個位元組,加5後,ptr已經指向了陣列a的合法範圍之外了。雖然這種情況在應用上會出問題,但在語法上卻是可以的。這也體現出了指標的靈活性。
如果上例中,ptr是被減去5,那麼處理過程大同小異,只不過ptr的值是被減去5乘sizeof(int),新的ptr指向的位址將比原來的ptr所指向的位址向低位址方向移動了20個位元組。
總結一下,乙個指標ptrold加上乙個整數n後,結果是乙個新的指標ptrnew,ptrnew的型別和ptrold的型別相同,ptrnew所指向的型別和ptrold所指向的型別也相同。ptrnew的值將比ptrold的值增加了n乘sizeof(ptrold所指向的型別)個位元組。就是說,ptrnew所指向的記憶體區將比ptrold所指向的記憶體區向高位址方向移動了n乘sizeof(ptrold所指向的型別)個位元組。乙個指標ptrold減去乙個整數n後,結果是乙個新的指標ptrnew,ptrnew的型別和ptrold的型別相同,ptrnew所指向的型別和ptrold所指向的型別也相同。ptrnew的值將比ptrold的值減少了n乘sizeof(ptrold所指向的型別)個位元組,就是說,ptrnew所指向的記憶體區將比ptrold所指向的記憶體區向低位址方向移動了n乘sizeof(ptrold所指向的型別)個位元組。
第三章。運算子&和*
這裡&是取位址運算子,*是...書上叫做「間接運算子」。&a的運算結果是乙個指標,指標的型別是a的型別加個*,指標所指向的型別是a的型別,指標所指向的位址嘛,那就是a的位址。*p的運算結果就五花八門了。總之*p的結果是p所指向的東西,這個東西有這些特點:它的型別是p指向的型別,它所占用的位址是p所指向的位址。
例五:
int a=12;
int b;
int *p;
int **ptr;
p=&a;//&a的結果是乙個指標,型別是int*,指向的型別是int,指向的位址是a的位址。
*p=24;//*p的結果,在這裡它的型別是int,它所占用的位址是p所指向的位址,顯然,*p就是變數a。
ptr=&p;//&p的結果是個指標,該指標的型別是p的型別加個*,在這裡是int**。該指標所指向的型別是p的型別,這裡是int*。該指標所指向的位址就是指標p自己的位址。
*ptr=&b;//*ptr是個指標,&b的結果也是個指標,且這兩個指標的型別和所指向的型別是一樣的,所以?amp;b來給*ptr賦值就是毫無問題的了。
**ptr=34;//*ptr的結果是ptr所指向的東西,在這裡是乙個指標,對這個指標再做一次*運算,結果就是乙個int型別的變數。
指標的概念
指標的概念 1.指標 pointer。所謂指標,就是乙個位址。2.指標變數,存放指標型別資料的變數。指標和指標變數一定要區別開來,指標變數就是乙個儲存指標以及位址資料的變數,而指標指的是被儲存位址。3.定義 int p 定義了乙個p,存放乙個int 型別的位址。型別決定了讀取資料時讀取多少個位元組。...
指標函式的概念
指標函式 指標函式是指帶指標的函式,即本質是乙個函式。我們知道函式都有返回型別 如果不返回值,則為無值型 只不過指標函式返回型別是某一型別的指標。其定義格式如下所示 返回型別識別符號 返回名稱 形式參數列 返回型別可以是任何基本型別和復合型別。返回指標的函式的用途十分廣泛。事實上,每乙個函式,即使它...
c 指標的概念
最簡單乙個概念就是引用,相當於給這個變數起了另乙個名字 eg a b 以後使用ab都可以修改這個變數。可以用於函式傳遞引數 hello string pointa astring 最重要的一點,就是宣告指標的時候 reference string pointa astring string poin...