用彙編的眼光看C (之指標1)03 1

2022-03-24 15:23:59 字數 3543 閱讀 2754

指標是我們在c/c++中經常遇到的一種資料型別。指標用的好,可以提高**的可讀性;但是如果使用不恰當,反而會造成很大的麻煩。指標,也就是指向某一 種資料型別的位址。這種型別很多,它可以是程式語言自帶的型別,比如說int、long、short、char、float、double、int;也可 是是指向某一種自定義資料型別,可以使union、struct或者是class;甚至指向的資料型別本身即是指標,比如說int*、char*、 short**;當然指標還可以是指向一片記憶體,表示具有一定長度的起始位址,比如說int(*pdata)[4];最後,指標還可以是函式指標,直接指 向函式執行的第乙個位元組。

(1)普通資料型別指標

普通資料型別指標相對概念比較簡單,它表示指向的區域就是普通資料型別的空間。我們可以看下面一段示例**:

[cpp]view plain

copy

43:       

intm = 10;  

004012f8   mov         dword ptr [ebp-4],0ah  

44:       char

* p = (

char

*) &m;  

004012ff   lea         eax,[ebp-4]  

00401302   mov         dword ptr [ebp-8],eax  

45:       float

* f = (

float

*) &m;  

00401305   lea         ecx,[ebp-4]  

00401308   mov         dword ptr [ebp-0ch],ecx  

46:       short

* s = (

short

*) &m;  

0040130b   lea         edx,[ebp-4]  

0040130e   mov         dword ptr [ebp-10h],edx  

47:       *p = 2;  

00401311   mov         eax,dword ptr [ebp-8]  

00401314   mov         byte ptr [eax],2  

48:       *f = 2.4f;  

00401317   mov         ecx,dword ptr [ebp-0ch]  

0040131a   mov         dword ptr [ecx],4019999ah  

49:       *s = 10;  

00401320   mov         edx,dword ptr [ebp-10h]  

00401323   mov         word ptr [edx],offset process+46h (00401326)  

上面的一段**出現了四種資料型別,三種指標,我們可以一一梳理一下。m、p、f、s都是函式內部的臨時變數,因為指標也是一種資料型別,它儲存的資料不 再是一種char或者是short、int資料,而是一種位址。所以我們對p、f、s進行複製的時候,都是把m的位址一一拷貝給他們的。所以雖然指標型別 不同,實際上p、f、s的數值是一樣的。下面對指標指向的空間進行資料賦值的時候,就和指標型別相關了。一般來說,如果指標為char型別,那麼計算就局 限在指標指向的那乙個位元組裡面;如果指標是int型別,那麼運算的範圍就是指標指向的連續4個位元組;當然如果指標是資料結構體或者是class型別,那麼 指標操作的記憶體區域就更大了。所以,我們返回到**的時候發現,*p=2只是操作了乙個byte,*f=2.4f的時候,操作的是四個byte、也就是 dword,*s=10的時候,賦值的就是乙個word,這裡0x401326處其實就是資料0x00 0a。函式內的變數進過這一番折騰之後,m數值還是10嗎?大家可以好好思考一下?(其實是0x4019000a)

(2)函式型別指標

下面是一段有趣的**,可以檢視函式的位址。

[cpp]view plain

copy

void

add()  

void

process(

int* q)  

}  這段**使用了嵌入式彙編,但是理解上面沒有什麼困難,感興趣的同學可以直接拷貝到vc上面進行編譯,當然還要加上標頭檔案和main函式。通過**,我們可以發現其實address就是乙個位址,call address其實和call add是一樣的。

(3)指標的指標

指標的指標,其實就是說我們指標指向的資料型別本身就是指標。但是,總之一句,指標是位址,那麼指向位址資料的指標本身也是位址。

[cpp]view plain

copy

46:       

int* pp = &p;  

004012ff   lea         eax,[ebp-4]  

00401302   mov         dword ptr [ebp-8],eax  

47:       int

** ppp = &pp;  

00401305   lea         ecx,[ebp-8]  

00401308   mov         dword ptr [ebp-0ch],ecx  

48:       int

*** pppp = &ppp;  

0040130b   lea         edx,[ebp-0ch]  

0040130e   mov         dword ptr [ebp-10h],edx  

49:       assert(sizeof

(p) == 4);  

50:       assert(sizeof

(pp) == 4);  

51:       assert(sizeof

(ppp) == 4);  

52:       assert(sizeof

(ppp) == 4);  

指標是一種儲存位址的資料型別,那麼指標的指標也是一種位址資料,儲存的也是位址。以此類推,指標的指標的指標呢。。。。。。上面的**已經清楚地說明了 這一點。雖然pp、ppp、pppp自身的意義有所差別,但是他們儲存的資料卻很簡單,也就是堆疊的位址。 pppp->ppp->pp->p,大家如果看懂了這個關係,就不會覺得指標很複雜了。如果還是不甚了了,可以把指標內容和指標位址分 別列印出來,就會發現他們的區別了。下面就是列印的結果:

[cpp]view plain

copy

p = 0xa, &p = 0x12ff20  

pp = 0x12ff20, &pp = 0x12ff1c  

ppp = 0x12ff1c, &ppp = 0x12ff18  

pppp = 0x12ff18, &pppp = 0x12ff14  

(待續)

用彙編的眼光看C (之指標1)

指標是我們在c c 中經常遇到的一種資料型別。指標用的好,可以提高 的可讀性 但是如果使用不恰當,反而會造成很大的麻煩。指標,也就是指向某一種資料型別的位址。這種型別很多,它可以是程式語言自帶的型別,比如說int long short char float double int 也可是是指向某一種自...

用彙編的眼光看C (之指標1)

指標是我們在c c 中經常遇到的一種資料型別。指標用的好,可以提高 的可讀性 但是如果使用不恰當,反而會造成很大的麻煩。指標,也就是指向某一種資料型別的位址。這種型別很多,它可以是程式語言自帶的型別,比如說int long short char float double int 也可是是指向某一種自...

用彙編的眼光看C (之指標1)

指標是我們在c c 中經常遇到的一種資料型別。指標用的好,可以提高 的可讀性 但是如果使用不恰當,反而會造成很大的麻煩。指標,也就是指向某一種資料型別的位址。這種型別很多,它可以是程式語言自帶的型別,比如說int long short char float double int 也可是是指向某一種自...