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

來源:互聯網
上載者:User

 【 聲明:著作權,歡迎轉載,請勿用於商業用途。  聯絡信箱:feixiaoxing @163.com】

 

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

    (1)普通資料類型指標

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

43:       int  m = 10;004012F8   mov         dword ptr [ebp-4],0Ah44:       char* p = (char*) &m;004012FF   lea         eax,[ebp-4]00401302   mov         dword ptr [ebp-8],eax45:       float* f = (float*) &m;00401305   lea         ecx,[ebp-4]00401308   mov         dword ptr [ebp-0Ch],ecx46:       short* s = (short*) &m;0040130B   lea         edx,[ebp-4]0040130E   mov         dword ptr [ebp-10h],edx47:       *p = 2;00401311   mov         eax,dword ptr [ebp-8]00401314   mov         byte ptr [eax],248:       *f = 2.4f;00401317   mov         ecx,dword ptr [ebp-0Ch]0040131A   mov         dword ptr [ecx],4019999Ah49:       *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)函數類型指標

    下面是一段有趣的代碼,可以查看函數的地址。

void add(){printf("hello!\n");}void process(int* q){int* address = (int*)add;__asm{call address}}

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

    (3)指標的指標

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

46:       int* pp = &p;004012FF   lea         eax,[ebp-4]00401302   mov         dword ptr [ebp-8],eax47:       int** ppp = &pp;00401305   lea         ecx,[ebp-8]00401308   mov         dword ptr [ebp-0Ch],ecx48:       int*** pppp = &ppp;0040130B   lea         edx,[ebp-0Ch]0040130E   mov         dword ptr [ebp-10h],edx49:       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,大家如果看懂了這個關係,就不會覺得指標很複雜了。如果還是不甚了了,可以把指標內容和指標地址分別列印出來,就會發現他們的區別了。下面就是列印的結果:

p = 0xa, &p = 0x12ff20pp = 0x12ff20, &pp = 0x12ff1Cppp = 0x12ff1C, &ppp = 0x12ff18pppp = 0x12ff18, &pppp = 0x12ff14

 

(待續)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.