C 指標理解

2021-06-29 15:21:12 字數 4294 閱讀 2361

一、指標的概念

本質上講指標也是一種變數,普通的變數包含的是實際的資料,而指標變數包含的是記憶體中的一塊位址,這塊位址指向某個變數或者函式,指標就是位址。指標是乙個指示器,它告訴程式在記憶體的哪塊區域可以找到資料。

二、指標的內容

指標的內容包含4部分:指標的型別,指標所指向的型別,指標的值,指標本身所占有的記憶體區。在初學指標時,指標的型別和指標所指向的型別是極容易搞混淆的,弄清楚這些概念,有助於我們正確的使用指標。

1.指標的型別

從語法的角度看,你只要把指標宣告語句裡的指標名字去掉,剩下的部分就是這個指標的型別。

int *ptr;

//指標的型別是int *

char *ptr; //指標的型別是char *

int **ptr; //指標的型別是 int **

int (*ptr)[3]; //指標的型別是 int(*)[3]

int *(*ptr)[4]; //指標的型別是 int *(*)[4]

2.指標所指向的型別

從語法上看,你只須把指標宣告語句中的指標名字和名字左邊的指標宣告符*去掉,剩下的就是指標所指向的型別。

當你通過指標來訪問指標所指向的記憶體區時,指標所指向的型別決定了編譯器將把那片記憶體區里的內容當做什麼來看待。

int *ptr; //指標所指向的型別是int  

char *ptr; //指標所指向的的型別是char

int **ptr; //指標所指向的的型別是 int *

int (*ptr)[3]; //指標所指向的的型別是 int()[3]

int *(*ptr)[4];//指標所指向的的型別是 int *()[4]

3.指標的值

指標的值是指標本身儲存的數值,這個值將被編譯器當作乙個位址,而不是乙個一般的數值。在32位程式裡,所有型別的指標的值都是乙個32位整數,因為32位程式裡記憶體位址全都是32位長。 

指標所指向的記憶體區就是從指標的值所代表的那個記憶體位址開始,長度為sizeof(指標所指向的型別)的一片記憶體區。以後,我們說乙個指標的值是xx,就相當於說該指標指向了以xx為首位址的一片記憶體區域;我們說乙個指標指向了某塊記憶體區域,就相當於說該指標的值是這塊記憶體區域的首位址。 

指標所指向的記憶體區和指標所指向的型別是兩個完全不同的概念。如int*p,指標所指向的型別已經有了,但由於指標還未初始化,所以它所指向的記憶體區是不存在的,或者說是無意義的。 

以後,每遇到乙個指標,都應該問問:這個指標的型別是什麼?指標指向的型別是什麼?該指標指向了**?

4.指標本身所占有的記憶體區

指標本身佔了多大的記憶體?你只要用函式sizeof(指標的型別)測一下就知道了。在32位平台裡,指標本身佔據了4個位元組的長度。

指標本身佔據的記憶體這個概念在判斷乙個指標表示式是否是左值時很有用。

三、看待指標型別和指標所指向的型別的方法。(我自己的理解)

int*p

來說,它可以寫成

int* p

,也可以寫成

int *p

。第一種的理解偏向於位址,就是p是乙個位址變數,p表示乙個十六進製制位址;第二種的寫法偏向於值,

*p是乙個整型變數,它能夠表示乙個整型值。 

這兩種寫法都正確,只是理解上不同,但是我認為,在理解指標型別和指標所指向的型別這兩個概念時,完全可以把它們兩個結合起來。 

想想我們使用指標的步驟:

宣告指標,為指標賦值,然後使用指標所指向的值。 

我們都知道指標是一種復合資料型別,它必須和基本的型別結合才能構成指標型別。 

那麼int*

就是一種復合的資料型別——整型指標型別。 

這樣就好解釋第一種寫法了,在宣告時,

int* p

,直接宣告p變數為整型指標型別,這是第一步。 

第二步就是為指標賦值了,p是指標型別,它存放的是位址,這裡假設我這樣為它賦值:p = &普通變數;(比如int a = 5;p=&a;)。 

第三步使用指標,在c++ primer中詳細的解釋了

*是解除引用的運算子(我的理解是位址解析運算子),如果p是位址,那麼

*p就是實際的值(比如上面對應的*p = 5)。

對於初學者來說,在理解它的含義時,完全可以跨過這一步,上面說了在宣告指標時

int* p

和int *p

這兩種寫法都可以,在宣告時我偏向第一種理解,在使用時我偏向第二種理解:畢竟我們使用的是值,而*p就是這個值。 

我的結論:對於

int* p

和int *p

的理解(也是對於指標型別和指標所指向的型別的理解),乙個指標包含兩部分,位址和值,指標宣告時宣告的是乙個位址變數(指標就是位址),在使用時使用的是指標所指向的值。或者說指標包含兩個型別:指標型別和指標所指向的型別,宣告時是宣告指標型別,使用時是使用指標所指向的型別。

int p[3];//p先和結合,說明p是乙個陣列,再和int結合,所以p是乙個int型陣列
int* p[3];//優先順序比*高,p是陣列,再加上int*,可以稱它為指標陣列,陣列的每乙個元素的值都為指標(位址)
int (*p)[3];//*p可以看作是普通變數,就回到第三種情況(int p[3]),但是這裡p是指標變數,它指向的是乙個包含3個整型數值的陣列。可以稱它為陣列指標,陣列中每乙個元素的值為普通整型值。
int** p;//int*代表指標型別,*是指標型別,所以p是指向int型指標的指標,p指向的型別是int*型別(int型指標)
int p(int);//這很明顯是乙個返回型別為int,並且帶乙個int型引數的函式
int (*p)(int);//p是函式指標,指向的是返回值為int並且帶乙個int引數的函式。這個宣告包含兩部分:函式變數+函式位址變數(姑且把函式也看做是變數)
int* (*p(int))[3];//這個有點複雜,它仍然是乙個函式指標。從*p(int)看,它是函式指標,帶乙個int引數;然後看,說明函式返回值為陣列,然後返回型別為int*。所以p是乙個指向返回值為int*型指標陣列,並且帶乙個int型引數的函式的指標

四、幾個demo

1.指標的算術運算

對乙個指標加1或者減1,實際上是加上或減去它所指向的資料的長度,所計算的結果是乙個新的位址值。

兩個相同型別的指標還可以做減法運算,得到的結果是乙個表示這兩個位址間該型別資料個數的整數值。

2.指標與陣列

int* p = &a[0];//第乙個元素的位址

int* p1 = a;//陣列位址(相同位址)

int main()

; short stacks[3] = ;

//兩種方式去獲取陣列的位址——陣列名或對陣列首元素進行求址運算

double* pw = wages;

short* ps = &stacks[0];

cout<<"pw = "<

3.結構指標

struct mystruct  

;

mystruct ss=;//宣告了結構物件ss,並把ss的三個成員初始化為20,30和40。

mystruct *ptr=&ss;//宣告了乙個指向結構物件ss的指標。它的型別是mystruct*,它指向的型別是mystruct。

int main()

4.函式指標

可以把乙個指標宣告成為乙個指向函式的指標。  

int fun1(int);
int main
...

C 指標理解

指標是c c 程式設計中的重要概念之一,也是最容易產生困惑並導致程式出錯的問題之一。利用指標程式設計可以表示各種資料結構,通過指標可使用主調函式和被調函式之間共享變數或資料結構,便於實現雙向資料通訊 指標能夠靈活的操作記憶體,合理的操作記憶體能夠使程式更高效。1.指標的概念 本質上講指標也是一種變數...

c 指標理解

const修飾指標有三種情況 const修飾指標 常量指標 const修飾常量 指標常量 const即修飾指標,又修飾常量 示例 int main 指標的理解 int a 10 p 表示位址 即 p a p 表示位址指向的內容 即 p 10 補充 const int p a 表示常量指標 int c...

C 指標理解

1.指標的概念 本質上講指標也是一種變數,普通的變數包含的是實際的資料,而指標變數包含的是記憶體中的一塊位址,這塊位址指向某個變數或者函式,指標就是位址。指標是乙個指示器,它告訴程式在記憶體的哪塊區域可以找到資料。2.指標的內容 指標的內容包含4部分 指標的型別,指標所指向的型別,指標的值,指標本身...