版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
運(yùn)行存儲(chǔ)分配
哈爾濱工業(yè)大學(xué)陳鄞第七章7.1存儲(chǔ)組織7.2靜態(tài)存儲(chǔ)分配7.3棧式存儲(chǔ)分配7.4非局部數(shù)據(jù)的訪問(wèn)7.5堆式存儲(chǔ)分配7.6符號(hào)表提綱編譯器在工作過(guò)程中,必須為源程序中出現(xiàn)的一些數(shù)據(jù)對(duì)象分配運(yùn)行時(shí)的存儲(chǔ)空間對(duì)于那些在編譯時(shí)刻就可以確定大小的數(shù)據(jù)對(duì)象,可以在編譯時(shí)刻就為它們分配存儲(chǔ)空間,這樣的分配策略稱為靜態(tài)存儲(chǔ)分配反之,如果不能在編譯時(shí)完全確定數(shù)據(jù)對(duì)象的大小,就要采用動(dòng)態(tài)存儲(chǔ)分配的策略。即在編譯時(shí)僅產(chǎn)生各種必要的信息,而在運(yùn)行時(shí)刻,再動(dòng)態(tài)的分配數(shù)據(jù)對(duì)象的存儲(chǔ)空間棧式存儲(chǔ)分配堆式存儲(chǔ)分配靜態(tài)和動(dòng)態(tài)分別對(duì)應(yīng)編譯時(shí)刻和運(yùn)行時(shí)刻7.1存儲(chǔ)組織靜態(tài)代碼區(qū)靜態(tài)數(shù)據(jù)區(qū)棧(Stack)區(qū)堆
(Heap)區(qū)動(dòng)態(tài)數(shù)據(jù)區(qū)域空閑內(nèi)存運(yùn)行時(shí)內(nèi)存的劃分使用過(guò)程(或函數(shù)、方法)作為用戶自定義動(dòng)作的單元的語(yǔ)言,其編譯器通常以過(guò)程為單位分配存儲(chǔ)空間過(guò)程體的每次執(zhí)行稱為該過(guò)程的一個(gè)活動(dòng)(activation)過(guò)程每執(zhí)行一次,就為它分配一塊連續(xù)存儲(chǔ)區(qū),用來(lái)管理過(guò)程一次執(zhí)行所需的信息,這塊連續(xù)存儲(chǔ)區(qū)稱為活動(dòng)記錄(activationrecord)活動(dòng)記錄實(shí)參臨時(shí)變量控制鏈訪問(wèn)鏈保存的機(jī)器狀態(tài)局部數(shù)據(jù)指向調(diào)用者的活動(dòng)記錄用來(lái)訪問(wèn)存放于其它活動(dòng)記錄中的非局部數(shù)據(jù)返回值活動(dòng)記錄的一般形式7.1存儲(chǔ)組織7.2靜態(tài)存儲(chǔ)分配7.3棧式存儲(chǔ)分配7.4非局部數(shù)據(jù)的訪問(wèn)7.5堆式存儲(chǔ)分配7.6符號(hào)表提綱在靜態(tài)存儲(chǔ)分配中,編譯器為每個(gè)過(guò)程確定其活動(dòng)記錄在目標(biāo)程序中的位置這樣,過(guò)程中每個(gè)名字的存儲(chǔ)位置就確定了因此,這些名字的存儲(chǔ)地址可以被編譯到目標(biāo)代碼中過(guò)程每次執(zhí)行時(shí),它的名字都綁定到同樣的存儲(chǔ)單元7.2靜態(tài)存儲(chǔ)分配適合靜態(tài)存儲(chǔ)分配的語(yǔ)言必須滿足以下條件數(shù)組上下界必須是常數(shù)不允許過(guò)程的遞歸調(diào)用不允許動(dòng)態(tài)建立數(shù)據(jù)實(shí)體滿足這些條件的語(yǔ)言有BASIC和FORTRAN等靜態(tài)存儲(chǔ)分配的限制條件順序分配法層次分配法常用的靜態(tài)存儲(chǔ)分配方法按照程序段出現(xiàn)的先后順序逐段分配存儲(chǔ)空間各過(guò)程的活動(dòng)記錄占用互不相交的存儲(chǔ)空間
1/222/153/184/176/105/23過(guò)程編號(hào)/所需存儲(chǔ)空間
過(guò)程存儲(chǔ)區(qū)域
10~21222~36
337~54
455~71
572~94
695~104共需要105個(gè)存儲(chǔ)單元優(yōu)點(diǎn):處理上簡(jiǎn)單缺點(diǎn):對(duì)內(nèi)存空間的使用不夠經(jīng)濟(jì)合理能用更少的空間么?順序分配法通過(guò)對(duì)過(guò)程間的調(diào)用關(guān)系進(jìn)行分析,凡屬無(wú)相互調(diào)用關(guān)系的并列過(guò)程,盡量使其局部數(shù)據(jù)共享存儲(chǔ)空間過(guò)程4(0~16)過(guò)程2(17~31)過(guò)程6(0~9)過(guò)程5(0~22)過(guò)程3(23~40)過(guò)程1(41~62)共需要63個(gè)存儲(chǔ)單元7/80如何分配?層次分配法1/222/153/184/176/105/23過(guò)程編號(hào)/所需存儲(chǔ)空間
B[n][n]:過(guò)程調(diào)用關(guān)系矩陣B[i][j]=1:表示第i個(gè)過(guò)程調(diào)用第j個(gè)過(guò)程B[i][j]=0:表示第i個(gè)過(guò)程不調(diào)用第j個(gè)過(guò)程
Units[n]:過(guò)程所需內(nèi)存量矩陣
123456101100020001013000011400000050000006000000層次分配算法base[i]:第i個(gè)過(guò)程局部數(shù)據(jù)區(qū)的基地址
allocated[i]:第i個(gè)過(guò)程局部數(shù)據(jù)區(qū)是否分配的標(biāo)志
voidMakeFortranBlockAllocated(int
*Units,int*base,intNoOfBlocks){/*
NoOfBlocksindicatinghowmanyblocksthereare
*/inti
,j,k,Sum;int*allocated;/*usedtoindicateiftheblockisallocated*/allocated=(int*)malloc(sizeof(int)*NoOfBlocks);for(i=0;i<NoOfBlocks;i++)/*Initialarraysbaseandallocated*/{base[i]=0;allocated[i]=0;}for(j=0;j<NoOfBlocks;j++)for(i=0;i<NoOfBlocks;i++){Sum=0;for(k=0;k<NoOfBlocks;k++)Sum+=B[i][k];
/*tocheckoutifblockicallssomeblockwhichhasnotbeenallocated*
/if(!Sum&&!allocated[i])
{/*Sum=0meansblockicallsnoblockwhichhasnotbeenallocated;allocated[i]=0;meansblockiisnotallocated*/allocated[i]=1;printf(′′%d:%d-%d/n′′,i,base[i],base[i]+Units[i]-1);for(k=0;k<NoOfBlocks;k++)
if(B[k][i])/*b[k][i]!=0maensblockkcallsblocki*/{/*Sinceblockkcallsi,itmustbeallocatedafterblocki.Itmeansthebaseofblockkmustbegreaterthanbaseofblocki*/if(base[k]<base[i]+Units[i])base[k]=base[i]-Units[i];B[k][i]=0;/*SinceblockinhasbeenallocatedB[k][i]shouldbemodified*/}}}free(allocated);}7.1存儲(chǔ)組織7.2靜態(tài)存儲(chǔ)分配7.3棧式存儲(chǔ)分配7.4非局部數(shù)據(jù)的訪問(wèn)7.5堆式存儲(chǔ)分配7.6符號(hào)表提綱有些語(yǔ)言使用過(guò)程、函數(shù)或方法作為用戶自定義動(dòng)作的單元,幾乎所有針對(duì)這些語(yǔ)言的編譯器都把它們的(至少一部分的)運(yùn)行時(shí)刻存儲(chǔ)以棧的形式進(jìn)行管理,稱為棧式存儲(chǔ)分配當(dāng)一個(gè)過(guò)程被調(diào)用時(shí),該過(guò)程的活動(dòng)記錄被壓入棧;當(dāng)過(guò)程結(jié)束時(shí),該活動(dòng)記錄被彈出棧這種安排不僅允許活躍時(shí)段不交疊的多個(gè)過(guò)程調(diào)用之間共享空間,而且允許以如下方式為一個(gè)過(guò)程編譯代碼:它的非局部變量的相對(duì)地址總是固定的,和過(guò)程調(diào)用的序列無(wú)關(guān)7.3棧式存儲(chǔ)分配用來(lái)描述程序運(yùn)行期間控制進(jìn)入和離開各個(gè)活動(dòng)的情況的樹稱為活動(dòng)樹樹中的每個(gè)結(jié)點(diǎn)對(duì)應(yīng)于一個(gè)活動(dòng)。根結(jié)點(diǎn)是啟動(dòng)程序執(zhí)行的main過(guò)程的活動(dòng)在表示過(guò)程p的某個(gè)活動(dòng)的結(jié)點(diǎn)上,其子結(jié)點(diǎn)對(duì)應(yīng)于被p的這次活動(dòng)調(diào)用的各個(gè)過(guò)程的活動(dòng)。按照這些活動(dòng)被調(diào)用的順序,自左向右地顯示它們。一個(gè)子結(jié)點(diǎn)必須在其右兄弟結(jié)點(diǎn)的活動(dòng)開始之前結(jié)束活動(dòng)樹p(1,3)q(1,0)q(2,3)p(5,9)q(5,5)q(7,9)mq(1,9)rp(1,9)q(1,3)q(5,9)p(2,3)q(2,1)q(3,3)p(7,9)q(7,7)q(9,9)inta[11];
voidreadArray()/*將9個(gè)整數(shù)讀入到a[1],…,a[9]中
*/{inti;…}intpartition(intm,intn){/*選擇一個(gè)分割值v,劃分a[m…n],使得a[m…p-1]小于v,a[p]=v,a[p+1…n]大于v。返回
p*/…
}voidquicksort(intm,intn){inti;if(n>m){i=partition(m,n);quicksort(m,i-1);quicksort(i+1,n);}}main(){readArray();a[0]=-9999;a[10]=9999;quicksort(1,9);}每個(gè)活躍的活動(dòng)都有一個(gè)位于控制棧中的活動(dòng)記錄例:一個(gè)快速排序程序的概要mrmainint
a[11]rint
i活動(dòng)樹控制棧mq(1,9)rp(1,9)mainint
a[11]q(1,9)int
ip(1,9)int
i活動(dòng)樹控制棧mq(1,9)rp(1,9)q(1,3)p(1,3)mainint
a[11]q(1,9)int
ip(1,3)int
i活動(dòng)樹控制棧q(1,3)int
imq(1,9)rp(1,9)q(1,3)p(1,3)mainint
a[11]q(1,9)int
i活動(dòng)樹控制棧q(1,3)int
iq(1,0)q(1,0)int
i當(dāng)一個(gè)過(guò)程是遞歸的時(shí),常常會(huì)有該過(guò)程的多個(gè)活動(dòng)記錄同時(shí)出現(xiàn)在棧中mq(1,9)rp(1,9)q(1,3)p(1,3)mainint
a[11]q(1,9)int
i活動(dòng)樹控制棧q(1,3)int
iq(1,0)q(2,3)int
iq(2,3)q(2,1)q(3,3)p(2,3)q(5,9)q(5,5)p(5,9)q(7,9)q(7,7)q(9,9)p(7,9)
每個(gè)活躍的活動(dòng)都有一個(gè)位于控制棧中的活動(dòng)記錄
活動(dòng)樹的根的活動(dòng)記錄位于棧底
程序控制所在的活動(dòng)的記錄位于棧頂
棧中全部活動(dòng)記錄的序列對(duì)應(yīng)于在活動(dòng)樹中到達(dá)當(dāng)前控制所在的活動(dòng)結(jié)點(diǎn)的路徑在調(diào)用者和被調(diào)用者之間傳遞的值一般被放在被調(diào)用者的活動(dòng)記錄的開始位置,這樣它們可以盡可能地靠近調(diào)用者的活動(dòng)記錄固定長(zhǎng)度的項(xiàng)被放置在中間位置控制連、訪問(wèn)鏈、機(jī)器狀態(tài)字在早期不知道大小的項(xiàng)被放置在活動(dòng)記錄的尾部棧頂指針寄存器top_sp指向活動(dòng)記錄中局部數(shù)據(jù)開始的位置,以該位置作為基地址被調(diào)用者的活動(dòng)記錄控制鏈訪問(wèn)鏈和機(jī)器狀態(tài)參數(shù)和返回值局部數(shù)據(jù)臨時(shí)數(shù)據(jù)參數(shù)和返回值控制鏈訪問(wèn)鏈和機(jī)器狀態(tài)局部數(shù)據(jù)臨時(shí)數(shù)據(jù)...棧top_sp調(diào)用者的活動(dòng)記錄設(shè)計(jì)活動(dòng)記錄的一些原則過(guò)程調(diào)用和過(guò)程返回都需要執(zhí)行一些代碼來(lái)管理活動(dòng)記錄棧,保存或恢復(fù)機(jī)器狀態(tài)等調(diào)用序列實(shí)現(xiàn)過(guò)程調(diào)用的代碼段。為一個(gè)活動(dòng)記錄在棧中分配空間,并在此記錄的字段中填寫信息返回序列恢復(fù)機(jī)器狀態(tài),使得調(diào)用過(guò)程能夠在調(diào)用結(jié)束之后繼續(xù)執(zhí)行一個(gè)調(diào)用代碼序列中的代碼通常被分割到調(diào)用過(guò)程(調(diào)用者)和被調(diào)用過(guò)程(被調(diào)用者)中。返回序列也是如此調(diào)用序列和返回序列
調(diào)用者計(jì)算實(shí)際參數(shù)的值
調(diào)用者將返回地址(程序計(jì)數(shù)器的值)放到被調(diào)用者的機(jī)器狀態(tài)字段中。將原來(lái)的top-sp值放到被調(diào)用者的控制鏈中。然后,增加top-sp的值,使其指向被調(diào)用者局部數(shù)據(jù)開始的位置
被調(diào)用者保存寄存器值和其它狀態(tài)信息
被調(diào)用者初始化其局部數(shù)據(jù)并開始執(zhí)行……參數(shù)和返回值控制鏈訪問(wèn)鏈保存的機(jī)器狀態(tài)局部數(shù)據(jù)和臨時(shí)數(shù)據(jù)參數(shù)和返回值控制鏈訪問(wèn)鏈保存的機(jī)器狀態(tài)局部數(shù)據(jù)和臨時(shí)數(shù)據(jù)……top_sp被調(diào)用者的活動(dòng)記錄調(diào)用者的活動(dòng)記錄調(diào)用序列
被調(diào)用者將返回值放到與參數(shù)相鄰的位置使用機(jī)器狀態(tài)字段中的信息,被調(diào)用者恢復(fù)top-sp和其它寄存器,然后跳轉(zhuǎn)到由調(diào)用者放在機(jī)器狀態(tài)字段中的返回地址盡管top-sp已經(jīng)被減小,但調(diào)用者仍然知道返回值相對(duì)于當(dāng)前top-sp值的位置。因此,調(diào)用者可以使用那個(gè)返回值……參數(shù)和返回值控制鏈訪問(wèn)鏈保存的機(jī)器狀態(tài)局部數(shù)據(jù)和臨時(shí)數(shù)據(jù)參數(shù)和返回值控制鏈訪問(wèn)鏈保存的機(jī)器狀態(tài)局部數(shù)據(jù)和臨時(shí)數(shù)據(jù)……top_sp被調(diào)用者的活動(dòng)記錄調(diào)用者的活動(dòng)記錄返回序列調(diào)用者填寫被調(diào)用者填寫被調(diào)用者填寫調(diào)用者更新被調(diào)用者恢復(fù)……參數(shù)和返回值控制鏈訪問(wèn)鏈保存的機(jī)器狀態(tài)局部數(shù)據(jù)和臨時(shí)數(shù)據(jù)參數(shù)和返回值控制鏈訪問(wèn)鏈保存的機(jī)器狀態(tài)局部數(shù)據(jù)和臨時(shí)數(shù)據(jù)……top_sp被調(diào)用者的活動(dòng)記錄調(diào)用者的活動(dòng)記錄調(diào)用者和被調(diào)用者之間的任務(wù)劃分在現(xiàn)代程序設(shè)計(jì)語(yǔ)言中,在編譯時(shí)刻不能確定大小的對(duì)象將被分配在堆區(qū)。但是,如果它們是過(guò)程的局部對(duì)象,也可以將它們分配在運(yùn)行時(shí)刻棧中。盡量將對(duì)象放置在棧區(qū)的原因:可以避免對(duì)它們的空間進(jìn)行垃圾回收,也就減少了相應(yīng)的開銷只有一個(gè)數(shù)據(jù)對(duì)象局部于某個(gè)過(guò)程,且當(dāng)此過(guò)程結(jié)束時(shí)它變得不可訪問(wèn),才可以使用棧為這個(gè)對(duì)象分配空間變長(zhǎng)數(shù)據(jù)…控制鏈和保存的機(jī)器狀態(tài)…指向a的指針指向c的指針指向b的指針…數(shù)組a數(shù)組b數(shù)組c控制鏈和保存的機(jī)器狀態(tài)top_sptop被調(diào)用者q的活動(dòng)記錄調(diào)用者p的活動(dòng)記錄q的數(shù)組p的數(shù)組訪問(wèn)動(dòng)態(tài)分配的數(shù)組7.1存儲(chǔ)組織7.2靜態(tài)存儲(chǔ)分配7.3棧式存儲(chǔ)分配7.4非局部數(shù)據(jù)的訪問(wèn)7.5堆式存儲(chǔ)分配7.6符號(hào)表提綱7.4非局部數(shù)據(jù)的訪問(wèn)一個(gè)過(guò)程除了可以使用過(guò)程自身定義的局部數(shù)據(jù)以外,還可以使用過(guò)程外定義的非局部數(shù)據(jù)語(yǔ)言可以分為兩種類型
支持過(guò)程嵌套聲明的語(yǔ)言可以在一個(gè)過(guò)程中聲明另一個(gè)過(guò)程例:Pascal
不支持過(guò)程嵌套聲明的語(yǔ)言不可以在一個(gè)過(guò)程中聲明另一個(gè)過(guò)程例:C例:C語(yǔ)言inta[11];
voidreadArray()/*將9個(gè)整數(shù)讀入到a[1],…,a[9]中
*/{inti;…}intpartition(intm,intn){/*選擇一個(gè)分割值v,劃分a[m…n],使得a[m…p-1]小于v,a[p]=v,
a[p+1…n]大于v。返回
p*/…
}voidquicksort(intm,intn){inti;if(n>m){i=partition(m,n);quicksort(m,i-1);quicksort(i+1,n);}}main(){readArray();
a[0]=-9999;
a[10]=9999;quicksort(1,9);}不支持過(guò)程嵌套聲明的語(yǔ)言過(guò)程中使用的非局部數(shù)據(jù)是全局?jǐn)?shù)據(jù)例:Pascal語(yǔ)言支持過(guò)程嵌套聲明的語(yǔ)言program
sort(input,output);
var
a:array[0..10]ofinteger;x:integer;
procedure
readarray;
var
i:integer;
begin…a…end{readarray};
procedure
exchange(i,j:integer);
begin
x=a[i];a[i]=a[j];a[j]=x;end{exchange};
procedure
quicksort(m,n:integer);
var
k,v:integer;
function
partition(y,z:integer):integer;
var
i,j:integer;
begin…a…v
…exchange(i,j)…end{partition};
begin…a…v…partition
…quicksort
…end{quicksort};
begin…a…readarray
…quicksort
…end{sort};過(guò)程中使用的非局部數(shù)據(jù)不一定都是全局?jǐn)?shù)據(jù),也可能是其它過(guò)程定義的數(shù)據(jù)例
procedure
A;
var
x:integer; …
procedure
B;
var
x:integer; …
procedure
C;
var
a:real;
begin…x
…end{C};
begin…end{B};
begin…end{A};名字x的當(dāng)前出現(xiàn)對(duì)應(yīng)的是哪個(gè)聲明語(yǔ)句?在程序的不同部分可能有同一名字的互相獨(dú)立的聲明x的一個(gè)聲明的作用域(scope)是指程序的一個(gè)區(qū)域,在其中對(duì)x的使用都指向這個(gè)聲明如果僅通過(guò)閱讀程序就可以確定一個(gè)聲明的作用域,那么這個(gè)語(yǔ)言使用的是靜態(tài)作用域。否則,這個(gè)語(yǔ)言使用的是動(dòng)態(tài)作用域包括C及其同類語(yǔ)言在內(nèi)的大多數(shù)語(yǔ)言使用靜態(tài)作用域C語(yǔ)言的作用域規(guī)則是基于程序結(jié)構(gòu)的,聲明的作用域由該聲明在程序中出現(xiàn)的位置隱含地決定稍后出現(xiàn)的語(yǔ)言,如C++、Java和
C#,也通過(guò)諸如public、private和protected等關(guān)鍵字的使用,提供對(duì)作用域的顯式的控制靜態(tài)作用域塊是聲明和語(yǔ)句的一個(gè)組合C使用括號(hào)“{”和“}”來(lái)界定一個(gè)塊另一種為同一目的使用begin和end的方法可以追溯到Algol塊結(jié)構(gòu)語(yǔ)言中聲明的靜態(tài)作用域規(guī)則如果名字x的聲明D屬于塊B,那么D的作用域包括整個(gè)B,但是以任意深度嵌套在B中、重新聲明了x的所有塊B'不在此作用域中例
procedure
A;
varx:integer; …
procedureB;
var
x:integer; …
procedure
C;
var
a:real;
begin…x…end{C};
begin…end{B};
begin…end{A};塊結(jié)構(gòu)語(yǔ)言中聲明的靜態(tài)作用域規(guī)則不支持過(guò)程嵌套聲明的語(yǔ)言在C系列語(yǔ)言中,各個(gè)變量要么在某個(gè)函數(shù)內(nèi)定義,要么在所有函數(shù)之外(全局地)定義一個(gè)全局變量v的作用域包含了該變量聲明后出現(xiàn)的所有函數(shù),但那些存在標(biāo)識(shí)符v的局部定義的地方除外在一個(gè)函數(shù)內(nèi)部聲明的變量的作用域就是這個(gè)函數(shù),或者如果該函數(shù)具有嵌套的語(yǔ)句塊,這個(gè)變量的作用域可能是該函數(shù)的部分區(qū)域無(wú)過(guò)程嵌套聲明時(shí)的靜態(tài)作用域變量的存儲(chǔ)分配和訪問(wèn)全局變量被分配在靜態(tài)區(qū),使用靜態(tài)確定的地址訪問(wèn)它們其它變量一定是棧頂活動(dòng)的局部變量。可以通過(guò)運(yùn)行時(shí)刻棧的top_sp指針訪問(wèn)它們無(wú)過(guò)程嵌套聲明時(shí)的數(shù)據(jù)訪問(wèn)根據(jù)塊結(jié)構(gòu)語(yǔ)言的靜態(tài)作用域規(guī)則,只要過(guò)程a的聲明包含過(guò)程b的聲明,過(guò)程b就可以訪問(wèn)過(guò)程a中聲明的對(duì)象program
sort
(input,output);
var
a:array[0..10]ofinteger;x:integer;
procedure
readarray;
var
i:integer;
begin…a…end{readarray};
procedure
exchange(i,j:integer);
begin
x=a[i];a[i]=a[j];a[j]=x;end{exchange};
procedure
quicksort(m,
n:integer);
var
k,v:integer;
function
partition(y,z:integer):integer;
var
i,j:integer;
begin…a…v
…exchange(i,
j)…end{partition};
begin…
a
…
v
…partition
…quicksort
…end{quicksort};
begin…a…readarray
…quicksort
…end{sort};有過(guò)程嵌套聲明時(shí)的數(shù)據(jù)訪問(wèn)運(yùn)行時(shí)如何訪問(wèn)在過(guò)程外聲明的數(shù)據(jù)?過(guò)程的嵌套深度不內(nèi)嵌在任何其它過(guò)程中的過(guò)程,設(shè)其嵌套深度為1如果一個(gè)過(guò)程p在一個(gè)嵌套深度為i的過(guò)程中定義,則設(shè)定p的嵌套深度為i+1變量的嵌套深度將變量聲明所在過(guò)程的嵌套深度作為該名字的嵌套深度嵌套深度
過(guò)程 嵌套深度sort 1
readarray 2
exchange 2
quicksort 2
partition 3program
sort(input,output);
var
a:array[0..10]ofinteger;x:integer;
procedure
readarray;
var
i:integer;
begin…a…end{readarray};
procedure
exchange(i,j:integer);
begin
x=a[i];a[i]=a[j];a[j]=x;end{exchange};
procedure
quicksort(m,n:integer);
var
k,v:integer;
function
partition(y,z:integer):integer;
var
i,j:integer;
begin…a…v
…exchange(i,j)…end{partition};
begin…a…v…partition
…quicksort
…end{quicksort};
begin…a…readarray
…quicksort
…end{sort};例靜態(tài)作用域規(guī)則:只要過(guò)程b的聲明嵌套在過(guò)程a的聲明中,過(guò)程b就可以訪問(wèn)過(guò)程a中聲明的對(duì)象可以在相互嵌套的過(guò)程的活動(dòng)記錄之間建立一種稱為訪問(wèn)鏈(Accesslink)的指針,使得內(nèi)嵌的過(guò)程可以訪問(wèn)外層過(guò)程中聲明的對(duì)象如果過(guò)程b在源代碼中直接嵌套在過(guò)程a中(b的嵌套深度比a的嵌套深度多1),那么b的任何活動(dòng)中的訪問(wèn)鏈都指向最近的a的活動(dòng)訪問(wèn)鏈(AccessLinks)sq(1,9)rp(1,9)q(1,3)q(1,0)p(1,3)q(2,3)q(5,9)eeprogram
sort(input,output);
var
a:array[0..10]ofinteger;x:integer;
procedure
readarray;
var
i:integer;
begin…a…end{readarray};
procedure
exchange(i,j:integer);
begin
x=a[i];a[i]=a[j];a[j]=x;end{exchange};
procedure
quicksort(m,n:integer);
var
k,v:integer;
function
partition(y,z:integer):integer;
var
i,j:integer;
begin…a…v
…exchange(i,j)…end{partition};
begin…a…v…partition
…quicksort
…end{quicksort};
begin…a…readarray
…quicksort
…end{sort};例s活動(dòng)樹sa訪問(wèn)鏈控制棧
過(guò)程 嵌套深度sort 1
readarray 2
exchange 2
quicksort 2
partition 3sr活動(dòng)樹控制棧
過(guò)程 嵌套深度sort 1
readarray 2
exchange 2
quicksort 2
partition 3sa訪問(wèn)鏈ri訪問(wèn)鏈r中的訪問(wèn)鏈指向s的活動(dòng)記錄,這不是因?yàn)閟調(diào)用了r,而是因?yàn)樵诔绦蛑校瑂是r外圍的最靠近r的嵌套函數(shù)sq(1,9)rp(1,9)活動(dòng)樹sa訪問(wèn)鏈控制棧
過(guò)程 嵌套深度sort 1
readarray 2
exchange 2
quicksort 2
partition 3q(1,9)v訪問(wèn)鏈p(1,9)i,j訪問(wèn)鏈ee訪問(wèn)鏈sq(1,9)rp(1,9)q(1,3)p(1,3)活動(dòng)樹
過(guò)程 嵌套深度sort 1
readarray 2
exchange 2
quicksort 2
partition 3sa訪問(wèn)鏈控制棧q(1,9)v訪問(wèn)鏈q(1,3)v訪問(wèn)鏈p(1,3)i,j訪問(wèn)鏈eee訪問(wèn)鏈假定棧頂?shù)倪^(guò)程b的嵌套深度是nb且b需要訪問(wèn)x,而x是在某個(gè)包圍b的嵌套深度為na的過(guò)程a中定義的一個(gè)元素(na≤nb)??梢园慈缦路椒ㄕ业絰從位于棧頂?shù)腷的活動(dòng)記錄開始,沿著訪問(wèn)鏈進(jìn)行nb
-na次從一個(gè)活動(dòng)記錄到另一個(gè)活動(dòng)記錄的查找,最終找到a的活動(dòng)記錄。這一定是當(dāng)前出現(xiàn)在棧中離b最近的a的活動(dòng)記錄。這個(gè)活動(dòng)記錄中包括要找的元素xsa訪問(wèn)鏈q(1,9)v訪問(wèn)鏈q(1,3)v訪問(wèn)鏈p(1,3)i,j訪問(wèn)鏈
過(guò)程嵌套深度sort 1
readarray 2
exchange 2
quicksort 2
partition 3利用訪問(wèn)鏈訪問(wèn)非局部數(shù)據(jù)的方法建立訪問(wèn)鏈的代碼屬于調(diào)用序列的一部分假設(shè)嵌套深度為nx的過(guò)程x調(diào)用嵌套深度為ny的過(guò)程y
(x→y)nx<ny的情況(外層調(diào)用內(nèi)層)y一定是直接嵌套在x中(例如:s→q,
q→p),因此,ny=nx+1在調(diào)用代碼序列中增加一個(gè)步驟:(利用控制鏈)在y的訪問(wèn)鏈中放置一個(gè)指向x的活動(dòng)記錄的指針sa訪問(wèn)鏈q(1,9)v訪問(wèn)鏈q(1,3)v訪問(wèn)鏈p(1,3)i,j訪問(wèn)鏈e訪問(wèn)鏈
過(guò)程嵌套深度sort 1
readarray 2
exchange 2
quicksort 2
partition 3訪問(wèn)鏈的建立sa訪問(wèn)鏈q(1,9)v訪問(wèn)鏈q(1,3)v訪問(wèn)鏈p(1,3)i,j訪問(wèn)鏈e訪問(wèn)鏈
過(guò)程嵌套深度sort 1
readarray 2
exchange 2
quicksort 2
partition 3建立訪問(wèn)鏈的代碼屬于調(diào)用序列的一部分假設(shè)嵌套深度為nx的過(guò)程x調(diào)用嵌套深度為ny的過(guò)程y
(x→y)nx<ny的情況(外層調(diào)用內(nèi)層)nx=ny的情況(本層調(diào)用本層)遞歸調(diào)用(例如:q→q)被調(diào)用者的活動(dòng)記錄的訪問(wèn)鏈與調(diào)用者的活動(dòng)記錄的訪問(wèn)鏈?zhǔn)窍嗤?,可以直接?fù)制訪問(wèn)鏈的建立sa訪問(wèn)鏈q(1,9)v訪問(wèn)鏈q(1,3)v訪問(wèn)鏈p(1,3)i,j訪問(wèn)鏈e訪問(wèn)鏈
過(guò)程嵌套深度sort 1
readarray 2
exchange 2
quicksort 2
partition 3建立訪問(wèn)鏈的代碼屬于調(diào)用序列的一部分假設(shè)嵌套深度為nx的過(guò)程x調(diào)用嵌套深度為ny的過(guò)程y
(x→y)nx<ny的情況(外層調(diào)用內(nèi)層)nx=ny的情況(本層調(diào)用本層)nx>ny的情況(內(nèi)層調(diào)用外層,如:p→e)過(guò)程x必定嵌套在某個(gè)過(guò)程z中,而z中直接定義了過(guò)程y從x的活動(dòng)記錄開始,沿著訪問(wèn)鏈經(jīng)過(guò)nx
-ny
+1步就可以找到離棧頂最近的z的活動(dòng)記錄。y的訪問(wèn)鏈必須指向z的這個(gè)活動(dòng)記錄訪問(wèn)鏈的建立7.1存儲(chǔ)組織7.2靜態(tài)存儲(chǔ)分配7.3棧式存儲(chǔ)分配7.4非局部數(shù)據(jù)的訪問(wèn)7.5堆式存儲(chǔ)分配7.6符號(hào)表提綱堆式存儲(chǔ)分配是把連續(xù)存儲(chǔ)區(qū)域分成塊,當(dāng)活動(dòng)記錄或其它對(duì)象需要時(shí)就分配塊的釋放可以按任意次序進(jìn)行,所以經(jīng)過(guò)一段時(shí)間后,對(duì)可能包含交錯(cuò)的正在使用和已經(jīng)釋放的區(qū)域堆式存儲(chǔ)分配鏈頭指針FREEA已占用塊記錄表堆式存儲(chǔ)分配的示意圖申請(qǐng)?jiān)O(shè)當(dāng)前自由塊總長(zhǎng)為M,欲申請(qǐng)長(zhǎng)度為n如果存在若干個(gè)長(zhǎng)度大于或等于n的存儲(chǔ)塊,可按以下策略之一進(jìn)行存儲(chǔ)分配取長(zhǎng)度m滿足需求的第1個(gè)自由塊,將長(zhǎng)度為m-n的剩余部分仍放在自由鏈中取長(zhǎng)度m滿足需求的最小的自由塊取長(zhǎng)度m滿足需求的最大的自由塊如果不存在長(zhǎng)度大于或等于n的存儲(chǔ)塊如果M≥n,將自由塊在堆中進(jìn)行移位和重組(對(duì)各有關(guān)部分都需作相應(yīng)的修改,是一件十分復(fù)雜和困難的工作)如果M<n,則應(yīng)采用更復(fù)雜的策略來(lái)解決堆的管理問(wèn)題申請(qǐng)?jiān)O(shè)當(dāng)前自由塊總長(zhǎng)為M,欲申請(qǐng)長(zhǎng)度為n如果存在若干個(gè)長(zhǎng)度大于或等于n的存儲(chǔ)塊,可按以下策略之一進(jìn)行存儲(chǔ)分配釋放只需將被釋放的存儲(chǔ)塊作為新的自由塊插入自由鏈中,并刪除已占?jí)K記錄表中相應(yīng)的記錄即可申請(qǐng)為實(shí)現(xiàn)堆式存儲(chǔ)管理須完成大量的輔助操作如排序、查表、填表、插入、刪除、……其空間和時(shí)間的開銷較大7.1存儲(chǔ)組織7.2靜態(tài)存儲(chǔ)分配7.3棧式存儲(chǔ)分配7.4非局部數(shù)據(jù)的訪問(wèn)7.5堆式存儲(chǔ)分配7.6符號(hào)表提綱符號(hào)表的組織為每個(gè)作用域(程序塊)建立一個(gè)獨(dú)立的符號(hào)表7.6符號(hào)表program
sort(input,output);
vara:array[0..10]ofinteger;
x:integer;
procedure
readarray;
var
i:integer;
begin
…a…
end;
procedure
exchange(i,j:integer);
begin
x=a[i];a[i]=a[j];a[j]=x;end;
procedure
quicksort(m,n:integer);
var
k,v:integer;
function
partition(y,z:integer):integer;
var
i,j:integer;
begin
…a…v…exchange(i,j)…end;
begin
…a…v…partition…quicksort…quicksort…end
;
begin
…a…readarray…quicksort…end;kint0vint4jint4iint0header48sortreadarraryaarray0xint44readarrayexchangeheader0exchangeheader8quicksortheader8partitionpartitionquicksortheader4
iint0例訪問(wèn)棧中的非局部數(shù)據(jù)kint0vint4jint4iint0header48sortreadarraryaarray0xint44readarrayexchangeheader0exchangeheader8quicksortheader8partitionpartitionquicksortheader4
iint0sa訪問(wèn)鏈q(1,9)v訪問(wèn)鏈q(1,3)v訪問(wèn)鏈p(1,3)i,j訪問(wèn)鏈實(shí)際上,這種為每個(gè)過(guò)程或作用域建立的符號(hào)表與編譯時(shí)的活動(dòng)記錄是對(duì)應(yīng)的。一個(gè)過(guò)程的非局部名字的信息可以通過(guò)掃描外圍過(guò)程的符號(hào)表而得到符號(hào)表的使用訪問(wèn)棧中的非局部數(shù)據(jù)構(gòu)造訪問(wèn)鏈kint0vint4jint4iint0header48sortreadarraryaarray0xint44readarrayexchangeheader0exchangeheader8quicksortheader8partitionpartitionquicksortheader4
iint0sa訪問(wèn)鏈q(1,9)v訪問(wèn)鏈q(1,3)v訪問(wèn)鏈p(1,3)i,j訪問(wèn)鏈e訪問(wèn)鏈x→y
nx<ny的情況(例:
s→q,
q→p)nx=ny的情況(例:
q→q)nx>ny的情況(例:p→e)符號(hào)表的使用當(dāng)在某一層的聲明語(yǔ)句中識(shí)別出一個(gè)標(biāo)識(shí)符(id的定義性出現(xiàn))時(shí),以此標(biāo)識(shí)符查相應(yīng)于本層的符號(hào)表如果查到,則報(bào)錯(cuò)并發(fā)出診斷信息“id重復(fù)聲明”否則,在符號(hào)表中加入新登記項(xiàng),將標(biāo)識(shí)符及有關(guān)信息填入當(dāng)在可執(zhí)行語(yǔ)句部分掃視到標(biāo)識(shí)符時(shí)(id的應(yīng)用性出現(xiàn))首先在該層符號(hào)表中查找該id,如果找不到,則到直接外層符號(hào)表中去查,如此等等,一旦找到,則在表中取出有關(guān)信息并作相應(yīng)處理如果查遍所有外層符號(hào)表均未找到該id,則報(bào)錯(cuò)并發(fā)出診斷信息“id未聲明”標(biāo)識(shí)符的基本處理方法嵌套過(guò)程聲明語(yǔ)句的文法 P
D
D
D
D|procid;D
S|id:T;在允許嵌套過(guò)程聲明的語(yǔ)言中,局部于每個(gè)過(guò)程的名字可以使用第6章介紹的方法分配相對(duì)地址;當(dāng)看到嵌套的過(guò)程p時(shí),應(yīng)暫時(shí)掛起對(duì)外圍過(guò)程q聲明語(yǔ)句的處理符號(hào)表的建立P
M
D
{addwidth(top(tblptr),top(offset));
pop(tblptr);
pop(offset);}M
{t=mktable(nil);
push(t,tblptr);
push(0,offset);}D
D1
D2Dp
procid;N
D1
S{t=top(tblptr);
addwidth(t,top(offset));
pop(tblptr);
pop(offset);
enterproc(top(tblptr),id.lexeme,t);}Dv
id:T;{enter(top(tblptr),id.lexeme,T.type,top(offset));
top(offset)
=top(offset)+T.width;}N
{t=mktable(top(tblptr));
push(t,tblptr);push(0,offset);}mktable(previous)創(chuàng)建一個(gè)新的符號(hào)表,并返回指向新表的指針。參數(shù)previous指向先前創(chuàng)建的符號(hào)表(外圍過(guò)程的符號(hào)表)enter(table,name,type,offset)在table指向的符號(hào)表中為名字name建立一個(gè)新表項(xiàng)addwidth(table,width)將table指向的符號(hào)表中所有表項(xiàng)的寬度之和width記錄在符號(hào)表的表頭中enterproc(table,name,newtable)在table指向的符號(hào)表中為過(guò)程name建立一條記錄,newtable指向過(guò)程name的符號(hào)表嵌套過(guò)程聲明語(yǔ)句的SDTprogram
sort(input,output);
vara:array[0..10]ofinteger;
x:integer;
procedure
readarray;
var
i:integer;
begin
…a…
end;
procedure
exchange(i,j:integer);
begin
x=a[i];a[i]=a[j];a[j]=x;end;
procedure
quicksort(m,n:integer);
var
k,v:integer;
function
partition(y,z:integer):integer;
var
i,j:integer;
begin
…a…v…exchange(i,j)…end;
begin
…a…v…partition…quicksort…quicksort…end
;
begin
…a…readarray…quicksort…end;program
sort;
vara:int[11];x:int;
proc
readarray;
var
i:int;{…}
proc
exchange;{…}
proc
quicksort;
var
k,v:int;
func
partitin;
var
i,j:int;{…}{…}{…}例headersortP
M
D
{addwidth(top(tblptr),top(offset));
pop(tblptr);pop(offset);}M
{t=mktable(nil);
push(t,tblptr);push(0,offset);}D
D1
D2Dp
procid;N
D1
S{t=top(tblptr);addwidth(t,top(offset));
pop(tblptr);pop(offset);enterproc(top(tblptr),id.lexeme,t);}Dv
id:T;{enter(top(tblptr),id.lexeme,T.type,top(offset));
top(offset)
=top(offset)+T.width;}N
{t=mktable(top(tblptr));push(t,tblptr);push(0,offset);}readarraryheaderprogram
sort;
vara:int[11];x:int;
proc
readarray;
var
i:int;{…}
proc
exchange;{…}
proc
quicksort;
var
k,v:int;
func
partitin;
var
i,j:int;{…}{…}{…}header
niloffsettblptraarray00044xint44480iint044readarray例headersortP
M
D
{addwidth(top(tblptr),top(offset));
pop(tblptr);pop(offset);}M
{t=mktable(nil);
push(t,tblptr);push(0,offset);}D
D1
D2Dp
procid;N
D1
S{t=top(tblptr);addwidth(t,top(offset));
pop(tblptr);pop(offset);enterproc(top(tblptr),id.lexeme,t);}Dv
id:T;{enter(top(tblptr),id.lexeme,T.type,top(offset));
top(offset)
=top(offset)+T.width;}N
{t=mktable(top(tblptr));push(t,tblptr);push(0,offset);}readarraryheaderprogram
sort;
vara:int[11];x:int;
proc
readarray;
var
i:int;{…}
proc
exchange;{…}
proc
quicksort;
var
k,v:int;
func
partitin;
var
i,j:int;{…}{…}{…}header
niloffsettblptraarray00040xint4448iint04readarrayexchangeheader00exchange例headersortP
M
D
{addwidth(top(tblptr),top(offset));
pop(tblptr);pop(offset);}M
{t=mktable(nil);
push(t,tblptr);push(0,offset);}D
D1
D2Dp
procid;N
D1
S{t=top(tblptr);addwidth(t,top(offset));
pop(tblptr);pop(offset);enterproc(top(tblptr),id.lexeme,t);}Dv
id:T;{enter(top(tblptr),id.lexeme,T.type,top(offset));
top(offset)
=top(offset)+T.width;}N
{t=mktable(top(tblptr));push(t,tblptr);push(0,offset);}readarraryheaderprogram
sort;
vara:int[11];x:int;
proc
readarray;
var
i:int;{…}
proc
exchange;{…}
proc
quicksort;
var
k,v:int;
func
partitin;
var
i,j:int;{…}{…}{…}header
niloffsettblptraarray00040xint4448iint04readarrayexchangeheader0exchangeheaderquicksort0k
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 小學(xué)三年級(jí)描寫同學(xué)的作文300字6篇
- 個(gè)人工作總結(jié)與參考計(jì)劃參考范文
- 陜西供排水項(xiàng)目可行性研究報(bào)告
- 普通員工辭職報(bào)告14篇
- 城鄉(xiāng)電網(wǎng)項(xiàng)目立項(xiàng)報(bào)告
- 個(gè)人年終述職報(bào)告怎么寫
- xx市天然氣管網(wǎng)及儲(chǔ)氣設(shè)施項(xiàng)目可行性研究報(bào)告
- 醫(yī)生晉升副高職稱述職報(bào)告
- 四川省宜賓市(2024年-2025年小學(xué)六年級(jí)語(yǔ)文)部編版專題練習(xí)((上下)學(xué)期)試卷及答案
- 合并案例分析
- 外科護(hù)理學(xué)全套課件
- 工程經(jīng)濟(jì)學(xué)完整版課件全套ppt教程
- 高中日語(yǔ) 授受關(guān)系 課件
- 上海市長(zhǎng)寧區(qū)2022年高考英語(yǔ)一模試卷(含答案)
- 軟件工程課程設(shè)計(jì)_《網(wǎng)上購(gòu)物系統(tǒng)項(xiàng)目》軟件設(shè)計(jì)說(shuō)明書
- 兩級(jí)CMOS運(yùn)算放大器設(shè)計(jì)
- 住宅項(xiàng)目規(guī)范(2022)
- 2012生物化學(xué)答疑-02
- 蘇教版新版五年級(jí)上冊(cè)科學(xué)全冊(cè)單元期末知識(shí)點(diǎn)梳理(1)
- 《雞兔同籠》ppt課件
- 制袋作業(yè)指導(dǎo)書
評(píng)論
0/150
提交評(píng)論