a一级爱做片免费观看欧美,久久国产一区二区,日本一二三区免费,久草视频手机在线观看

新聞中心

EEPW首頁 > 嵌入式系統 > 牛人業話 > C語言的那些小秘密之堆棧

C語言的那些小秘密之堆棧

作者: 時間:2015-03-02 來源:網絡 收藏
編者按:何為堆棧?首先要明確堆棧是兩種數據結構。棧是硬件,堆是一種動態存儲結構,但是它們倆個又是如何共存的呢?  

  在講解之前,我們先要來說說其實我們常說的是兩種數據結構。那么什么是堆什么又是棧呢?

本文引用地址:http://www.j9360.com/article/270300.htm

  棧,是硬件。主要作用表現為一種數據結構,是只能在某一端插入和刪除的特殊線性表。它按照后進先出的原則存儲數據,先進入的數據被壓入棧底,最后的數據在棧頂,需要讀數據的時候從棧頂開始彈出數據(最后一個數據被第一個讀出來)。棧是允許在同一端進行插入和刪除操作的特殊線性表。允許進行插入和刪除操作的一端稱為棧頂(top),另一端為棧底(bottom);棧底固定,而棧頂浮動;棧中元素個數為零時稱為空棧。插入一般稱為進棧(PUSH),刪除則稱為退棧(POP)。 棧也稱為先進后出表。棧可以用來在函數調用的時候存儲斷點,做遞歸時要用到棧!

  以上定義是在經典計算機科學中的解釋。

  在計算機系統中,棧則是一個具有以上屬性的動態內存區域。程序可以將數據壓入棧中,也可以將數據從棧頂彈出。在i386機器中,棧頂由稱為esp的寄存器進行定位。壓棧的操作使得棧頂的地址減小,彈出的操作使得棧頂的地址增大。

  棧在程序的運行中有著舉足輕重的作用。最重要的是棧保存了一個函數調用時所需要的維護信息,這常常稱之為幀或者活動記錄。堆棧幀一般包含如下幾方面的信息:

  1. 函數的返回地址和參數

  2. 臨時變量:包括函數的非靜態局部變量以及編譯器自動生成的其他臨時變量。

  堆,是一種動態存儲結構,實際上就是數據段中的自由存儲區,它是中使用的一種名稱,常常用于動態數據的存儲分配。堆中存入一數據,總是以2字節的整數倍進行分配,地址向增加方向變動。堆可以不斷進行分配直到沒有堆空間為止,也可以隨時進行釋放、再分配,不存在次序問題。

  堆和棧在使用時相向生長,棧向上生長,即向小地址方向生長,而堆向下增長,即向大地址方向,其間剩余部分是自由空間。使用過程中要防止增長過度而導致覆蓋。

  一般的程序我們都是使用小內存模式。

  明白了堆和棧的概念之后我們來看一個面試的c語言題目。代碼要相關要求如下所示:

  #include

  using namespace std;

  void print()

  {

  //這里進行打印arr數組,print不準傳參數

  }

  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};//數值隨即

  print();

  return 0;

  }

  剛剛一開始看到這個題目時,你可能有點發懵,心想可能在不傳遞參數的情況下打印arr數組的內容,但是看看我們的標題就應該知道該題跟棧有關系,在做之前我們先來回顧幾個知識點。

  push操作先修改指針,后將信息入棧。

  ESP為堆棧指針,棧頂有ESP寄存器來定位。壓棧的操作使得棧頂的地址減小,彈出的操作使得棧頂的地址增大。

  EBP是32位的BP,EBP是基址指針,EBP與BP的關系就像AX與AL、AH的關系一樣。BP為基指針寄存器,用它課直接存取堆棧中的數據,他的作用在調用函數時保存ESP,使函數結束時可以正確返回。

  c的默認函數壓棧操作為:

  參數是從右向左壓棧的,默認四字節對齊,函數里面定義的變量是默認對齊方式----變量首地址是自身結構體里邊最大標準數據類型字節的整數倍。

  我們先來看看上面這段代碼的匯編語句:

  //*******************************************start*********************************************//

  .file "push.c"

  .text

  .globl print

  .type print, @function

  print:

  pushl %ebp

  movl %esp, %ebp

  popl %ebp

  ret

  .size print, .-print

  .section .rodata

  .LC0:

  .string "fdsafdsafdsafdsafdsafdsafdsa"

  .text

  .globl main

  .type main, @function

  main:

  pushl %ebp

  movl %esp, %ebp

  andl $-16, %esp

  subl $64, %esp

  movl %gs:20, %eax

  movl %eax, 60(%esp)

  xorl %eax, %eax

  movl $0, 44(%esp)

  movl $0, 40(%esp)

  movl $.LC0, 36(%esp)

  movb $102, 51(%esp)

  movl $32, 8(%esp)

  movl $43, 12(%esp)

  movl $3, 16(%esp)

  movl $567, 20(%esp)

  movl $987, 24(%esp)

  movl $21, 28(%esp)

  movl $56, 32(%esp)

  call print

  movl $0, %eax

  movl 60(%esp), %edx

  xorl %gs:20, %edx

  je .L3

  call __stack_chk_fail

  .L3:

  leave

  ret

  .size main, .-main

  .ident "GCC: (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2"

  .section .note.GNU-stack,"",@progbits

  //*******************************************end*********************************************//

  看看上面的匯編代碼,我們的重點放在紅色字體部分,在函數的開頭部分都有這么兩行代碼:

 pushl %ebp --------------------------->保存上一個函數的棧底

  movl %esp, %ebp --------------------------->用來保存當前堆棧指針的值

  ebp存放當前函數棧低的地址,就是說ebp可以看做一個指針,指向棧頂,而其實棧頂存放的數據就是上一個函數的ebp的值,即就是main函數的棧底。

c語言相關文章:c語言教程



上一頁 1 2 下一頁

關鍵詞: C語言 堆棧

評論


相關推薦

技術專區

關閉