談C C 指標精髓(三)

2021-06-07 02:42:43 字數 3750 閱讀 8085

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的值加上5乘sizeof(int),在32位程式中就是加上了5乘4=20.由於位址的單位是位元組,故現在的ip所指向的位址比起加5後的ip所指向的位址來說,向高位址方向移動了20個位元組。在這個例子中,沒加5前的ip指向陣列a的第0號單元開始的四個位元組,加5後,ptr已經指向了陣列a的合法範圍之外了。雖然這種情況在應用上會出問題,但在語法上卻是可以的。這也體現出了指標的靈活性。

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

總結一下,乙個指標ipold加上乙個整數n後,結果是乙個新的指標ipnew,ipnew的型別和ipold的型別相同,ipnew所指向的型別和ipold所指向的型別也相同。ipnew的值將比ipold的值增加了n乘sizeof(ipold所指向的型別)個位元組。就是說,ipnew所指向的記憶體區將比ipold所指向的記憶體區向高位址方向移動了n乘sizeof(ipold所指向的型別)個位元組。

乙個指標ipold減去乙個整數n後,結果是乙個新的指標ipnew,ipnew的型別和ipold的型別相同,ipnew所指向的型別和ipold所指向的型別也相同。ipnew的值將比ipold的值減少了n乘sizeof(ipold所指向的型別)個位元組,就是說,ipnew所指向的記憶體區將比ipold所指向的記憶體區向低位址方向移動了n乘sizeof(ipold所指向的型別)個位元組。

1.4.3關係運算

指向同乙個陣列中的不同元素的兩個指標可以進行各種關係運算。例如:

ip1==ip2表示ip1和ip2指向同一陣列元素

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

ip1指標變數還可以與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 C 指標精髓 一

摘要 指標是c和c 語言程式設計中最重要的概念之一,也是最容易產生困惑並導致程式出錯的問題之一。利用指標程式設計可以表示各種資料結構,通過指標可使用主調函式和被調函式之間共享變數或資料結構,便於實現雙向資料通訊 並能像組合語言一樣處理記憶體位址,從而編出精練而高效的程式。指標極大地豐富了 和c 語言...

C C 指標之三

指標變數的賦值運算有以下幾種形式 int a int ip a int a int ip ip a 把整型變數 a的位址賦予整型指標變數 ipint a int pa a int pb pb pa 把a 的位址賦予指標變數pb 由於pa,pb均為指向整型變數的指標變數,因此可以相互賦值。int a ...

C C 指標 陣列與記憶體管理(三)

關於c c 的記憶體管理,博主發現一篇博文已經總結的很好了。記憶體管理 這裡做幾點總結 1 函式體內的區域性變數儲存在棧上,但棧的記憶體容量有限,在linux下可以使用ulimit s檢視棧的記憶體容量。在程式中注意不要超過這個值。當相應的範圍結束時,區域性變數就不能在使用。2 使用malloc n...