談C/C++指針精髓(3)[轉帖]

1.4指針的運算

 

1.4.1賦值運算

指針變量的賦值運算有以下幾種形式:

1.4.1.1指針變量初始化賦值如下:

int a;

int *ip=&a;

1.4.1.2把一個變量的地址賦予指向相同數據類型的指針變量。例如:

int a;

int *ip;

ip=&a;             //把整型變量a的地址賦予整型指針變量ip

1.4.1.3把一個指針變量的值賦予指向相同類型變量的另一個指針變量。例如:

int a;

int *pa=&a;

int *pb;

pb=pa;              //a的地址賦予指針變量pb

由於pa,pb均爲指向整型變量的指針變量,因此可以相互賦值。

1.4.1.4把數組的首地址賦予指向數組的指針變量。例如:

int a[5],*pa;

pa=a;               //數組名錶示數組的首地址,故可賦予指向數組的指針變量pa

也可寫爲:

pa=&a[0];           //數組第一個元素的地址也是整個數組的首地址也可賦予pa

當然也可採取初始化賦值的方法:

int a[5],*pa=a;

以上是一些基本的數組賦值方法,後面我們會詳細討論指針在數組中的使用。

1.4.1.5把字符串的首地址賦予指向字符類型的指針變量。例如:

char *pc;

pc="c language";

或用初始化賦值的方法寫爲:

char *pc=" c language ";

這裏應說明的是並不是把整個字符串裝入指針變量, 而是把存放該字符串的字符數組的首地址裝入指針變量。

1.4.1.6把函數的入口地址賦予指向函數的指針變量。例如:

int (*pf)();

pf=f;                //f爲函數名

1.4.2加減運算

對於指向數組的指針變量,可以加上或減去一個整數n。設ip是指向數組a的指針變量,則ip+n,ip-n,ip++,++ip,ip--,--ip 運算都是合法的。指針變量加或減一個整數n的意義是把指針指向的當前位置(指向某數組元素)向前或向後移動n個位置。應該注意,數組指針變量向前或向後移動一個位置和地址加1或減1 在概念上是不同的。因爲數組可以有不同的類型, 各種類型的數組元素所佔的字節長度是不同的。如指針變量加1,即向後移動1 個位置表示指針變量指向下一個數據元素的首地址。而不是在原地址基礎上加1。看如下例子:

char a[20];

int*ip=a;

...

ip++;

在上例中,指針ip的類型是int*,它指向的類型是int,它被初始化爲指向整形變量a。接下來的第3句中,指針ip被加了1,編譯器是這樣處理的:它把指針ip的值加上了sizeof(int),在32位程序中,是被加上了4。由於地址是用字節做單位的,故ip所指向的地址由原來的變量a的地址向高地址方向增加了4個字節。

由於char類型的長度是一個字節,所以,原來ptr是指向數組a的第0號單元開始的四個字節,此時指向了數組a中從第4號單元開始的四個字節。再看如下例子:

char a[20];

int*ip=a;

  ...

ip+=5;

在這個例子中,ip被加上了5,編譯器是這樣處理的:將指針ip的值加上5sizeof(int),在32位程序中就是加上了54=20。由於地址的單位是字節,故現在的ip所指向的地址比起加5後的ip所指向的地址來說,向高地址方向移動了20個字節。在這個例子中,沒加5前的ip指向數組a的第0號單元開始的四個字節,加5後,ptr已經指向了數組a的合法範圍之外了。雖然這種情況在應用上會出問題,但在語法上卻是可以的。這也體現出了指針的靈活性。

如果上例中,ip是被減去5,那麼處理過程大同小異,只不過ip的值是被減去5sizeof(int),新的ip指向的地址將比原來的ip所指向的地址向低地址方向移動了20個字節。

總結一下,一個指針ipold加上一個整數n後,結果是一個新的指針ipnewipnew的類型和ipold的類型相同,ipnew所指向的類型和ipold所指向的類型也相同。ipnew的值將比ipold的值增加了nsizeof(ipold所指向的類型)個字節。就是說,ipnew所指向的內存區將比ipold所指向的內存區向高地址方向移動了nsizeof(ipold所指向的類型)個字節。

一個指針ipold減去一個整數n後,結果是一個新的指針ipnewipnew的類型和ipold的類型相同,ipnew所指向的類型和ipold所指向的類型也相同。ipnew的值將比ipold的值減少了nsizeof(ipold所指向的類型)個字節,就是說,ipnew所指向的內存區將比ipold所指向的內存區向低地址方向移動了nsizeof(ipold所指向的類型)個字節。

1.4.3關係運算

指向同一個數組中的不同元素的兩個指針可以進行各種關係運算。例如:

ip1==ip2表示ip1ip2指向同一數組元素

ip1>ip2表示ip1處於高地址位置

ip1<ip2表示ip2處於低地址位置

指針變量還可以與0比較。設ip爲指針變量,則ip==0表明ip是空指針,它不指向任何變量;ip!=0表示ip不是空指針。空指針是由對指針變量賦予0值而得到的。例如:

#define NULL 0 

int *ip=NULL;

 對指針變量賦0值和不賦值是不同的。指針變量未賦值時,可以是任意值,是不能使用的。否則將造成意外錯誤。而指針變量賦0值後,則可以使用,只是它不指向具體的變量而已。

1.4.4取地址運算符‘&’和取內容運算符‘*

取地址運算符&是單目運算符,其結合性爲自右至左,其功能是取變量的地址。

取內容運算符*是單目運算符,其結合性爲自右至左,用來表示指針變量所指的變量。在*運算符之後跟的變量必須是指針變量。需要注意的是指針運算符*和指針變量說明中的指針說明符* 不是一回事。在指針變量說明中,‘*’是類型說明符,表示其後的變量是指針類型。而表達式中出現的‘*’則是一個運算符用以表示指針變量所指的變量。如下例子:

int a=12;

int b;

int *p;

int **ptr;

p=&a;   //&a的結果是一個指針,類型是int*,指向的類型是int,指向的地址是a

//地址。

*p=24;   //*p的結果,在這裏它的類型是int,它所佔用的地址是p所指向的地址。

ptr=&p; //&p的結果是個指針,該指針的類型是p的類型加個*,在這裏是int **。該

//指針所指向的類型是p的類型,這裏是int*。該指針所指向的地址就是指針

//p自己的地址。

*ptr=&b;//*ptr是個指針,&b的結果也是個指針,且這兩個指針的類型和所指向的類型//是一樣的,所以用&b來給*ptr賦值就是毫無問題的了。

**ptr=34;//*ptr的結果是ptr所指向的東西,在這裏是一個指針,對這個指針再做一次*

//運算,結果就是一個int類型的變量。

1.4.5關於括號組合

在解釋組合說明符時, 標識符右邊的方括號和圓括號優先於標識符左邊的“*”號,而方括號和圓括號以相同的優先級從左到右結合。但可以用圓括號改變約定的結合順序。

閱讀組合說明符的規則是“從裏向外”。從標識符開始,先看它右邊有無方括號或園括號,如有則先作出解釋,再看左邊有無*號。 如果在任何時候遇到了閉括號,則在繼續之前必須用相同的規則處理括號內的內容。

1.5指針表達式

    一個表達式的最後結果如果是一個指針,那麼這個表達式就叫指針表式。所以指針表達式也具有指針所具有的四個要素:指針的類型,指針所指向的類型,指針指向的內存區,指針自身佔據的內存。(預知後事如何,且聽下回分解!!!)

 
 

作者簡介:

馬偉,現任大方軟件開發工程師,在C家族(CC++C# 呵呵,因爲都有個C,所以我習慣稱爲C家族)方面有一定的見解,希望和廣大技術朋友共同交流。

E-MAIL[email protected] QQ:328941810 MSN[email protected]

網站和個人主頁:www.itspzo.com|

最後版權聲明一下:本文章歸本作者所有,任何個人和公司不得隨意把本文章的部分或者全部用於商業目的,如有轉載或者其他目的請聯繫作者。呵呵!!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章