二 指標的定義及運算

2021-06-22 20:09:04 字數 4156 閱讀 6156

**:

上一講已經說過,指標是一種變數,它也有自己的位址,但由於它是專門用來存放位址的變數,所以把它認為是種特殊的變數,既然有著特殊的身份,那麼也理應受到特殊的待遇,下面來看看它享受了那些優待。

1.指標的定義

在c語言中,定義乙個普通的變數(如整型數),我們這樣做:int i; 而定義乙個指標變數(指標)我們需要這樣做:int *p ;  還記得嗎,乙個矩形中的值是有型別的,可能是整型,可能是字元型……,它們原本是「清白」的,無型別的,是我們通過一些手段使它們有了型別。當我們做出int i; 這樣乙個定義時,編譯器就會分配乙個位址(例如200)並和i 關聯起來,而int將限定編譯器把這個區域中的內容作為整型數看待。

現在我們又有了int *p;這個定義,假設p是指向變數i的(見下圖),p中存的是變數i的位址。* 表示p是乙個指標,而int表示p中所存的位址對應的變數(即變數i)的型別是int。

我們將int稱為指標p的基型別,或指標p所指向的變數的型別。

類似地,我們可以有: char  *s ;   ( s是指向char型變數的指標 )

float  *f ;    ( f是指向float型變數的指標 )

double  *d ;  ( d是指向double型變數的指標 )

由此得到宣告乙個指標變數(指標)的一般形式 : 基型別  * 指標名;

有一點要注意,在定義指標時,以下兩種方式都是允許的,例如:

int  *ptr1;

int*  ptr2;

但一般比較傾向用第一種,因為可以避免以下的誤解:

int*  prt1,   ptr2;

這樣的定義方式,容易使人誤以為ptr2也是乙個指標,事實上並不是,prt2是乙個int型變數,以下的定義方式中ptr1與ptr2才都是指標:

int* ptr1,  *ptr2;

2.指標的運算

<1>.&(address-of operator)取位址操作符:

究竟如何使乙個指標指向乙個變數呢?後面的語句給出了解答:int *p = &i;& 用於取乙個物件的位址(本文說的物件是泛指的某一事物,如變數,陣列等,和

c++中的物件概念不同)

小擴充套件:(下面大括號中的內容,出涉指標的朋友可以跳過,當然也可以作為擴充套件知識)

<2>.* (dereference operator) 解引用操作符

* 在定義時用來說明乙個變數是指標,而在定義了乙個指標之後,我們使用(引用)指標時,*p表示的是p所指向的物件(即i)。也就是說,對於乙個已定義的指標使用 * 操作符,將訪問這個指標所指向的物件,我們來看下面的程式:

#include

int main()

程式輸出結果為: 2

2對於 * 操作符,由於它有兩個等價的術語dereference和indirection ,所以在國內的書籍中你會看到各種翻譯方法,如:解引用、解除引用、反引用、反向引用、間接引用、間接訪問……

只要你知道它是用來訪問乙個指標所指向的物件的,那麼不管它叫什麼都不重要了。還是那句話,弄懂是什麼,不要在乎叫什麼,如果你理解了它的真正含義,大可以簡潔地稱它為「星號」操作符!

3.指標的初始化

ansi c定義了零指標常量(即null)的概念:乙個具有

0值的整形常量表示式

,或者0值表示式被強制轉換為void *型別

,則稱為空指標常量,它可以用來初始化或賦給任何型別的指標(即null指標)。也就是說,我們可以將0、

0l、'/0'

、2–2

、0*5

以及(void*)0

賦給乙個任何型別的指標,此後這個指標就成為乙個空指標

,由系統保證空指標不指向任何物件或函式。

ansi c為此定義了乙個

巨集null,用來表示

空指標常量

。大多數c語言的實現中null是採用後面這種方式定義的:

#define  null  ((void*)0)。

對指標進行初始化時常用的有以下幾種方式:

1.採用null或空指標常量,如:int *p = null;或 char *p = 2-2; 或float*p = 0;

都是ok的 !

3.將乙個指標常量賦給乙個指標,如:long *p = (long *)0xfffffff0;ok的 !

4.將乙個t型別陣列的名字賦給乙個相同型別的指標,如:char ary[100]; char *cp = ary;

6.將乙個字串常量賦給乙個字元指標,如:char *cp = 「abcdefg」;ok的 !

對指標進行初始化或賦值的實質

是將位址或同型別

(或相相容的型別

)的指標賦給它,而不管這個位址是怎麼取得的。要注意的是:對於乙個不確定要指向何種型別的指標,在定義它之後最好把它初始化為

null

,並在解引用這個指標時對它進行檢驗,防止解引用野指標。另外,為程式中任何新建立的變數提供乙個合法的初始值是乙個好習慣,它可以幫你避免一些不必要的麻煩。

4.void *型指標

ansi c定義了一種void *型指標,表示定義乙個指標,但不指定它指向何種型別的資料。但void *型指標作為一種通用的指標,可以和其它任何型別的指標(函式指標除外)相互轉化而不需要型別強制轉換,但

不能對它進行解引用及下標操作。c語言中的malloc函式的返回值就是乙個void *型指標,我們可以把它直接賦給乙個其他型別的指標,但從安全的程式設計風格角度以及相容性上講,最好還是將返回的指標強制轉換為所需的型別,另外,malloc在無法滿足請求時會通過返回乙個空指標來作為「記憶體分配失敗」的訊號,所以要注意返回值指標的判空。

5.指向指標的指標

在指標初始化的第5種方式中提到了用乙個指標的位址來初始化乙個指標。回憶一下上一講的內容:指標是一種變數,它也有自己的位址,所以它本身也是可用指標指向的物件。我們可以將指標的位址存放在另乙個指標中,如:

int i = 5000;

int *pi = &i;

int **ppi =π

此時的ppi即是乙個指向指標的指標,下圖表示了這些物件:

i的位址為108,pi的內容就是i的位址,而pi的位址為104,ppi的內容即是pi的位址。對ppi解引用照常會得到ppi所指的物件,所獲得的物件是指向int型變數的指標pi。想要真正地訪問到i.,必須對ppi進行兩次解引用,如下面**所示:

printf("%d\n", i );

printf("%d\n", *pi );

printf("%d\n", **ppi );

以上三條語句的輸出均為5000。

前言

1.指標到底是什麼

3.指標與陣列的「愛恨情仇」

4.分清函式指標和指標函式

5.指標與結構

6.使用指標時的「陷阱」

後記

int* prt1,   ptr2; 前乙個位指標,後乙個位字元變數。

這樣的定義方式,容易使人誤以為ptr2也是乙個指標,事實上並不是,prt2是乙個int型變數,以下的定義方式中ptr1與ptr2才都是指標:

int* ptr1,  *ptr2;兩個都是指標。

但如果是

typedef intp int *;

intp ptr1,ptr2 ; 則兩個都為指標。

&的實質:當對乙個型別t物件進行 & 操作時,返回的是乙個「指向t的指標」型別的常量,即指標常量。

void *型指標作為一種通用的指標,可以和其它任何型別的指標(函式指標除外)相互轉化而不需要型別強制轉換,但

不能對它進行解引用及下標操作

二 指標的定義及運算

二 指標的定義及運算1 指標的定義 在c語言中,定義乙個普通的變數 如整型數 我們這樣做 int i 而定義乙個指標變數 指標 我們需要這樣做 int p 還記得嗎,乙個矩形中的值是有型別的,可能是整型,可能是字元型 它們原本是 清白 的,無型別的,是我們通過一些手段使它們有了型別。當我們做出int...

指標學習二 指標 位址

通過位址的呼叫來改變變數的值 includevoid f int p void g int k int main void f int p void g int k i 0063fe9c p 0063fe9c p 6 k 26定義乙個變數p,它位於2000單元,該單元存放了變數x的位址1000。此時...

C語言 二 指標

一 指標概述 1.簡介 2.初始化 1 先定義後初始化 int a 10 int p p a 2 定義並初始化 int a 10 int p a 備註 在資料型別後,變數名稱前的 是乙個說明符,用來說明該變數是乙個指標變數。如果前面沒有資料型別,如 p,這裡的 是乙個指標運算子,用來取出指標變數所指...