新聞中心

EEPW首頁(yè) > 嵌入式系統(tǒng) > 牛人業(yè)話(huà) > C語(yǔ)言的那些小秘密之堆棧

C語(yǔ)言的那些小秘密之堆棧

作者: 時(shí)間:2015-03-02 來(lái)源:網(wǎng)絡(luò) 收藏
編者按:何為堆棧?首先要明確堆棧是兩種數(shù)據(jù)結(jié)構(gòu)。棧是硬件,堆是一種動(dòng)態(tài)存儲(chǔ)結(jié)構(gòu),但是它們倆個(gè)又是如何共存的呢?  

  明白了上面的內(nèi)容,那么我們就可以實(shí)現(xiàn)題目的要求了。代碼如下所示:

本文引用地址:http://butianyuan.cn/article/270300.htm

  #include

  using namespace std;

  void print()

  {

  //這里進(jìn)行排序,print不準(zhǔn)傳參數(shù)

 unsigned int _ebp;

 __asm{

  mov _ebp,ebp

  }

  int *p=(int *)(*(int *)_ebp-4-4-4-4-8-7*4);

  for(int i=0;i<7;i++)

  cout<

  }

  int main()

  {

  int s=0;

  int ss=0;

  char *str="fdsafdsafdsafdsafdsafdsafdsa";

  char fdsa='f';

  char srt[8];

  int arr[]={32,43,3,567,987,21,56};//數(shù)值隨即

  print();

  return 0;

  }

  其中用紅色標(biāo)記的部分是一個(gè)重點(diǎn),用匯編語(yǔ)句mov _ebp,ebp;來(lái)獲得ebp寄存器的值,存放在_ebp中,ebp存放當(dāng)前函數(shù)棧底的地址,就是說(shuō)ebp可以看做一個(gè)指針,指向棧頂,因?yàn)?pushl %ebp,所以棧頂存放的數(shù)據(jù)就是上一個(gè)函數(shù)的ebp的值,即就是main函數(shù)的棧底。由此可知*(int*)_ebp意思就是取出棧頂?shù)臄?shù)據(jù),即main函數(shù)的棧底。棧中數(shù)據(jù)的存儲(chǔ)方式是根據(jù)聲明的先后順序來(lái)的,所以了為了能夠?qū)rr數(shù)組進(jìn)行打印,我們要計(jì)算出數(shù)組首地址的存儲(chǔ)地址,由于變量的壓棧方式默認(rèn)是四字節(jié)對(duì)齊,所以我們使用一句int *p=(int *)(*(int *)_ebp-4-4-4-4-8-7*4);來(lái)得到數(shù)組的首地址,有人可能很疑惑了,為什么這句 char *str="fdsafdsafdsafdsafdsafdsafdsa";聲明的變量只是占了四字節(jié)呢?!這里要注意了,因?yàn)橹羔樧兞康牡刂吩?2位的計(jì)算機(jī)中占用四個(gè)字節(jié),他的內(nèi)容并不存儲(chǔ)在棧中,而是在堆中,棧中僅僅是保存了指向堆的指針。講到這兒基本上都豁然開(kāi)朗了吧。看看下面的運(yùn)行結(jié)果吧!



  為了強(qiáng)調(diào)默認(rèn)的字節(jié)對(duì)齊概念,我們?cè)賮?lái)修改下代碼得到的運(yùn)行結(jié)果可以上面得做一個(gè)比較。

  代碼如下,紅色部分為修改代碼。

  #include

  using namespace std;

  void print()

  {

  //這里進(jìn)行排序,print不準(zhǔn)傳參數(shù)

  unsigned int _ebp;

  __asm{

  mov _ebp,ebp

  }

  int *p=(int *)(*(int *)_ebp-4-4-4-4-8-7*4);

  for(int i=0;i<7;i++)

  cout<

  }

  int main()

  {

  int s=0;

  int ss=0;

  char *str="fdsafdsafdsafdsafdsafdsafdsa";

  char fdsa='f';

  char srt[6];

  int arr[]={32,43,3,567,987,21,56};//數(shù)值隨即

  print();

  return 0;

  }

  運(yùn)行結(jié)果為:



  如果我們修改了 char srt[6];之后去把int *p=(int *)(*(int *)_ebp-4-4-4-4-8-7*4);修改為int *p=(int *)(*(int *)_ebp-4-4-4-4-6-7*4);,注意紅色部分的對(duì)比,運(yùn)行結(jié)果就變?yōu)榱耍?/p>



  顯然對(duì)比可知運(yùn)行結(jié)果出錯(cuò)了。在此多次一舉的給出對(duì)比無(wú)非是為了大家能夠?qū)ψ止?jié)的對(duì)齊方式加以重視。當(dāng)然以上內(nèi)容難免有錯(cuò),畢竟c語(yǔ)言博大精深,如果有不正確的地方,請(qǐng)糾正。

c語(yǔ)言相關(guān)文章:c語(yǔ)言教程



上一頁(yè) 1 2 下一頁(yè)

關(guān)鍵詞: C語(yǔ)言 堆棧

評(píng)論


相關(guān)推薦

技術(shù)專(zhuān)區(qū)

關(guān)閉