C 深入淺出 C 指標運算和指標安全總結

2021-10-02 21:25:54 字數 4108 閱讀 6466

(1)指標 p

pp 指向變數 a

aa 意思是 指標變數的內容值是 a

aa 的位址,也就是說p = &a

int b; <==> int *const b;

陣列名b

bb也是個指標(位址),只不過它是乙個con

stconst

cons

t 指標,也就是說b

bb的內容值不能被修改,b

bb指向某個地方的事實不能被更改,b = &b[0]

(2)說明:c++中*的三個角色

(3)指標的大小

指標的大小也就是位址的大小是跟機器有關係的,有些是4,有些是8

指標p可以加上或減去乙個整數n,但指標的這種運算的意義和通常的數值的加減

運算的意義是不一樣的,它是以單元為單位,如p指向int型整數,則乙個單位是sizeof(int)

(1)示例1

char a[20]

="you are my friend"

;int

*ptr=

(int

*)a;

ptr = ptr +

3;

char陣列的每個單位是乙個位元組,而指標ptr指向的單元是4個位元組

所以沒加3前的 ptr 指向陣列a的第1 - 4個位元組(看作乙個整體),加3後,ptr已經指向了陣列a的第13 - 16個位元組,即指向a[12] - a[15]這部分

(2)示例2

#include

using

namespace std;

intmain()

;int

*ptr = array;

// 陣列名array是位址,把它賦給指標ptr

for(

int i =

0; i <

20; i++

) ptr = array;

for(

int i =

0; i <

16; i +=4

)return0;

}

(3)char **p; p++;分析執行後p的值

char m =

'c';

char

*t =

&m;// char *t = "hello"; // 字串是位址常量(第乙個字元的位址)

char

**p =

&t;

p是個二級指標

總結乙個指標(位址)ptrold加(減)乙個整數 n 後,結果是乙個新的指標(位址)ptrnew

ptrnew的型別和ptrold的型別相同,ptrnew所指向的型別和ptrold所指向的型別也相同

ptrnew 的值將比 ptrold 的值增加(減少)了 n 乘sizeof(ptrold 所指向的型別)個位元組

也就是說:ptrnew 所指向的記憶體區將比 ptrold 所指向的記憶體區向高(低)位址方向移動了 n 乘sizeof(ptrold 所指向的型別)個位元組。

指標和指標進行加減:

陣列名array本質是乙個指標,所以

int array=

;int

*p = array;

記住一點

*(p + 4) 和 p[4]是等價的

*(array + 4) 和 array[4]是等價的

array[0]等價於p[0],因為p = array;

所以實際上,上面四個都是等價的

而對於二維陣列int a[3][4]

這裡的陣列名a相對於乙個二級指標,a是乙個指向一維陣列(指標)的指標

a + 1 = &a[1]

*(a + 1) = *&a[1] = a[1]

a[0]是第乙個一維陣列的陣列名(位址),若令指標p = a[0],則*(p + 3) =*( a[0]+3) = a[0][3]

更清晰地解釋可以看下面這張圖

char a[10]char *a是不一樣的

說明:char *p = "abcd";

"abcd"是個位址常量,它等於第乙個字元a的位址

struct node node;

node tu;

node *p =

&tu;

只要記住一點:(*p).data和p->data; 是等價的

(1)示例1

int a;

int*p =

&a;p +=1

;*p =

8;

上面的**存在嚴重的錯誤,因為第三行**p += 1執行後,p指向了整型變數a相鄰的高位址方向的一塊儲存區域,而我們居然用第四行**往這塊區域裡寫入資料,這非常危險,因為我們不知道它裡面原來的內容是什麼,萬一是系統十分重要的資料呢

在陣列int a[10]時類似地操作可行,那是因為我們已經申請了乙個長度長度為10的連續空間,這部分空間是我們已知的且可隨意寫資料的

所以說,我們在使用指標時一定要非常清楚:這個指標究竟指向了**

(2)示例2

當我們使用指標的強制型別轉換p1=(type *)p2 時,如果 sizeof(p2 的型別) 大於 sizeof(ptr1 的型別),那麼在使用指標 p1 來訪問 p2 所指向的儲存區時是安全的。否則是會出現嚴重問題的

char t =

'a';

int*p;

p =(

int*

)&t;

*p =

520;

執行**,可能不會報錯,但這存在著安全隱患,因為p指向的是字元a以及和它相鄰高位址方向的三個位元組,而後面三個位元組的內容我們並不知道是什麼,萬一很重要的呢

(3)下面的**是安全的,而且可以說明我的機器是小端模式

因為從t最後的值為48,可以看出p指向的是int4個位元組中的低位元組,而強制轉換的char指標p預設是指向int4個位元組中低位址的位元組的,所以可以說明我的機器是小端模式(低位元組在低位址)

int t =7;

char

*p;

p =(char*)

&t;*p =

'0';

// 對應48:00110000 char 乙個位元組:0-127

cout <<

*p << endl;

cout << t << endl;

// 輸出48

野指標野指標:指標變數指向非法的記憶體空間

示例:

#include

using

namespace std;

intmain()

空指標和野指標都不是我們自己申請的空間,所以不要隨意地去訪問它

C 深入淺出之指標

1 指標陣列 char str 10 指標陣列,顧名思義是乙個陣列,其元素是乙個指標。上述 是定義乙個指標陣列,其陣列元素為指向字元的指標。所謂指標陣列,重頭戲在於陣列,指標可以抽象為修飾符,那麼如何來理解指標陣列呢?很簡單,的優先順序高於 因此先被結合,加上陣列名,就構成了陣列。2 陣列指標 in...

深入淺出c 之 this指標

前言 c語言中的陣列指標和指標陣列 陣列指標,是指向陣列的指標的縮寫 指標陣列,是存放指標的陣列的縮寫。其實很多時候,往往因為簡寫和縮寫帶給我們很多困惑。我曾想過不用簡稱去學習,但在很多時候,我們查詢的書籍文件和文章中還是會頻頻出現這樣的簡稱,所以有必要扣一下字眼了。1 int p 3 優先順序大於...

C 深入淺出Dynamic

我們知道c 是乙個強型別語言,也就是說編譯器在編譯的時候會堅持資料型別是否正確。但是dynamic的出現讓c 具有了弱語言型別的特性。編譯器在編譯的時候不再對型別進行檢查,編譯器預設dynamic物件支援你想要的任何特性。dynamic dy 100 dy.name 89 dy.getname 上例...