版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
ch07--運行環(huán)境2024/4/17ch07運行環(huán)境2運行環(huán)境程序運行時刻的環(huán)境,即運行中程序的信息是怎樣存儲和訪問的。執(zhí)行過程中,程序中數(shù)據(jù)的存取是通過對應的存儲單元來進行的。存儲組織與管理早期的計算機上,存儲管理工作是由程序員自己來完成有了高級語言之后,程序中使用的存儲單元都由標識符來表示,它們對應的內(nèi)存地址由編譯程序在編譯時或由其生成的目標程序在運行時進行分配。存儲的組織及管理是編譯程序要完成的一個復雜而又十分重要的工作。ch07運行環(huán)境3運行環(huán)境7.1程序運行時的存儲組織7.2存儲分配策略7.3訪問非局部名字7.4參數(shù)傳遞機制小結(jié)ch07運行環(huán)境47.1程序運行時的存儲組織概念:過程與活動一、程序運行空間的劃分二、控制棧與活動記錄三、作用域及名字綁定ch07運行環(huán)境5概念:過程與活動過程的定義一個聲明語句把一個標識符和一個語句聯(lián)系起來標識符是過程名,語句是過程體。過程的分類過程:沒有返回值的過程函數(shù):有返回值的過程也可以把函數(shù)、一個完整的程序看作過程過程引用:過程名出現(xiàn)在一個可執(zhí)行語句中參數(shù):形參、實參ch07運行環(huán)境6活動活動一個過程的每次執(zhí)行稱為它的一次活動如果一個過程在執(zhí)行中,則稱它的這次活動是活著的過程與活動過程是一個靜態(tài)概念,活動是一個動態(tài)概念過程與活動之間可以是1:1、1:m的關(guān)系遞歸過程,同一時刻可能有若干個活動是活著的每個活動都有自己獨立的存儲空間/數(shù)據(jù)空間PPPP有3個活著的活動P有2個活著的活動P有1個活著的活動ch07運行環(huán)境7活動的生存期程序執(zhí)行時,過程之間的控制流是連續(xù)的過程的每一次執(zhí)行都是從過程體的起點開始,最后控制返回到直接跟隨本次調(diào)用點的位置?;顒拥纳嫫谶^程體的執(zhí)行中,第一步和最后一步之間的一系列步驟的執(zhí)行時間過程P的一次活動的生存期,包括執(zhí)行過程P所調(diào)用的過程的時間,以及這些過程所調(diào)用的過程的時間如果a和b是過程的活動,那么它們的生存期要么是不重疊,要么是嵌套的。遞歸過程:如果一個過程,它的不同活動的生存期可以嵌套,則這個過程是遞歸的直接遞歸、間接遞歸abababch07運行環(huán)境8一、程序運行空間的劃分編譯程序在編譯源程序時,向操作系統(tǒng)申請一塊內(nèi)存區(qū)域,以便被編譯程序在其中運行代碼區(qū)/保存目標代碼靜態(tài)數(shù)據(jù)區(qū)控制棧堆編譯時可以確定代碼段的長度,可以放在一個靜態(tài)確定的區(qū)域內(nèi)編譯時可確定大小的數(shù)據(jù)對象,放在靜態(tài)確定的區(qū)域內(nèi),目標地址可以編入目標代碼中用于管理過程的活動、保存斷點的現(xiàn)場信息,用于返回時的恢復程序控制下進行的動態(tài)存儲分配,分配在堆中,如Pascal中new函數(shù)???ch07運行環(huán)境9二、控制棧與活動記錄控制棧:用于保存控制信息的棧。程序執(zhí)行過程中使用控制棧來保存活動的生存蹤跡及活動的運行環(huán)境?;顒佑涗洠阂粋€連續(xù)的存儲塊記錄過程在一次執(zhí)行中所需要的信息通常,活動記錄分配在控制棧中(像Pascal、C)當一個過程被調(diào)用時,被調(diào)用過程的一次新的活動被激活,在棧頂為該活動創(chuàng)建一個新的活動記錄來保存其環(huán)境信息;當活動結(jié)束,控制從被調(diào)用過程返回時,釋放該活動記錄,使調(diào)用過程的活動記錄成為棧頂活動記錄,即恢復調(diào)用過程的執(zhí)行環(huán)境。ch07運行環(huán)境10活動記錄的內(nèi)容返回值實參區(qū)域控制鏈訪問鏈機器狀態(tài)域局部數(shù)據(jù)區(qū)臨時數(shù)據(jù)區(qū)存放中間計算結(jié)果在本次活動中,為過程中定義的局部變量分配的存儲空間保存斷點的現(xiàn)場信息,寄存器、PSW等指向直接外圍過程的最近一次活動的活動記錄的指針,用于對非局部名字的訪問指向調(diào)用過程的活動記錄的指針,用于本活動結(jié)束時的恢復調(diào)用過程提供給本活動的實參值本活動返回給調(diào)用過程的值根據(jù)確定每個域所需空間大小的時間早晚安排其位置。(1)早:中間晚:兩頭(2)用于通信:前面自己用的:后面ch07運行環(huán)境11活動記錄中內(nèi)容的安排原則大小能夠較早確定的區(qū)域放在活動記錄的中間,大小較晚才能確定、并且變化較多的區(qū)域放在活動記錄的兩頭??刂奇湣⒃L問鏈、機器狀態(tài)域,是編譯器設(shè)計的一部分,編譯器構(gòu)造時就可以確定它們的大小,所以把這些區(qū)域放在活動記錄的中間。參數(shù)域放在前面,便于調(diào)用過程進行參數(shù)傳遞,同時,被調(diào)用過程也可很方便地進行訪問。返回值域放在最前面,便于調(diào)用過程可以根據(jù)自己的棧指針訪問該區(qū)域,取回返回值。局部數(shù)據(jù)/臨時數(shù)據(jù)安排在最后,其大小變化不會影響到活動記錄中其他數(shù)據(jù)的存取。并且調(diào)用過程也無權(quán)訪問被調(diào)用過程中的局部數(shù)據(jù)。ch07運行環(huán)境12局部數(shù)據(jù)的安排常識:程序運行時使用連續(xù)的存儲空間內(nèi)存可編址的最小單位是字節(jié)一個機器字由若干個字節(jié)組成一個名字所需存儲空間的大小由其類型決定需多個字節(jié)表示的數(shù)據(jù)對象,存放在連續(xù)字節(jié)的存儲塊中,第一個字節(jié)的地址作為它的地址局部數(shù)據(jù)的安排局部數(shù)據(jù)區(qū)是在編譯過程中檢查聲明語句時安排的長度可變的數(shù)據(jù)對象,放在該區(qū)域之外數(shù)據(jù)對象的存儲安排受目標機器編址限制的影響ch07運行環(huán)境13編址限制的影響整數(shù)加法指令可能要求整數(shù)的地址能夠被4整除要求地址對齊如:x:integer;y:char;z:integer;
為求分配上的全局統(tǒng)一,而多余出來的無用空間叫做填塞(padding)如果char占一個字節(jié),integer占2個字節(jié),x、y、z共需要5個字節(jié)。如果要求從雙字節(jié)地址分配,則需要為這三個變量分配6個字節(jié),ch07運行環(huán)境14三、作用域及名字綁定聲明是一個把信息與名字聯(lián)系起來的語法結(jié)構(gòu)顯式聲明(如PASCAL中的聲明:vari:integer)隱含聲明(如FORTRAN程序)在一個程序的不同部分可能有對同一個名字的相互獨立的聲明一個聲明起作用的程序部分稱為該聲明的作用域語言的作用域規(guī)則決定了當這樣的名字在程序正文中出現(xiàn)時應該使用哪一個聲明Pascal中的名字遵循“最近嵌套原則”編譯過程中,名字的作用域信息記錄在符號表中ch07運行環(huán)境15名字的綁定把名字對應到存儲單元的過程名字與存儲單元的對應關(guān)系:1:11:m當environment把一個存儲單元S與一個名字X聯(lián)系起來時,稱X受限于S。S的大小取決于X的類型一個活動中的名字與其存儲單元之間一個遞歸過程中的名字與其存儲單元之間名字X存儲單元S
S的內(nèi)容Venvironmentstate地址為名字的左值名字的右值ch07運行環(huán)境16與存儲組織與管理有關(guān)的其他問題名字的存儲空間如何組織、名字綁定的方法等主要取決于對以下問題的回答:過程是否可遞歸?當控制從過程的一次活動返回時,對局部名字的值如何處理?過程是否可以引用非局部的名字?過程調(diào)用時如何傳遞參數(shù)?過程是否可以作為參數(shù)傳遞?過程可否作為結(jié)果被返回?存儲空間能否在程序控制下進行動態(tài)分配?存儲空間是否必須顯式地歸還?ch07運行環(huán)境177.2存儲分配策略運行時刻存儲空間的劃分,除目標代碼外,其余三種數(shù)據(jù)空間采用的存儲分配策略是不同的。靜態(tài)存儲分配:編譯時對所有數(shù)據(jù)對象分配存儲空間棧式存儲分配:運行時把存儲器作為棧進行管理,數(shù)據(jù)對象分配在棧中堆式存儲分配:運行時把存儲器組織成堆結(jié)構(gòu),對用戶提出的存儲空間的申請與歸還進行存儲分配與回收。一、靜態(tài)存儲分配二、棧式存儲分配三、堆式存儲分配ch07運行環(huán)境18一、靜態(tài)存儲分配條件:源程序中出現(xiàn)的各種數(shù)據(jù)所需要的存儲空間的大小在編譯時可以確定存儲分配:編譯時,為他們分配固定的存儲空間運行時:總是使用這些存儲空間過程每次被激活,同一名字都使用相同的存儲空間允許局部名字的值在活動結(jié)束后被保留下來當控制再次進入時,局部名字的值即上次離開時的值數(shù)據(jù)對象:每個過程的活動記錄的位置及大小記錄中每一個名字所占用的存儲空間的位置及大小數(shù)據(jù)在運行時刻的地址可以填入到目標代碼中ch07運行環(huán)境19靜態(tài)存儲分配策略對源語言的限制數(shù)據(jù)對象的大小和它們在內(nèi)存中的位置必須在編譯時都能夠確定不允許過程遞歸調(diào)用因為使用靜態(tài)存儲分配,一個過程里聲明的局部數(shù)據(jù)在該過程的所有活動中都結(jié)合到同一個地址。不能建立動態(tài)數(shù)據(jù)結(jié)構(gòu)因為沒有在運行時進行存儲分配的機制。ch07運行環(huán)境20靜態(tài)存儲分配策略的實現(xiàn)編譯器處理聲明語句時,每遇到一個變量名就創(chuàng)建一個符號表條目,填入相應的屬性,包括目標地址。每個變量所需空間的大小由其類型確定,并且在編譯時刻是已知的。根據(jù)名字出現(xiàn)的先后順序,連續(xù)分配空間nametypeaddress...lengthN10n1N2n1n2N3n1+n2n3.........代碼區(qū)
數(shù)據(jù)區(qū)N1N2程序的邏輯空間0LA...ch07運行環(huán)境21PROGRAMCNSUMECHARACTER*50BUFINTEGERNEXTCHARACTERC,PRDUCEDATANEXT/1/,BUF/
/6C=PRDUCE()BUF(NEXT:NEXT)=CNEXT=NEXT+1IF(C.NE.
)GOTO6WRITE(*,
(A)
)BUFENDFortran程序舉例CHARACTERFUNCTIONPRDUCE()CHARACTER*80BUFFERINTEGERNEXTSAVEBUFFER,NEXTDATANEXT/81/IF(NEXT.GT.80)THENREAD(*,
(A)
)BUFFERNEXT=1ENDIFPRDUCE=BUFFER(NEXT:NEXT)NEXT=NEXT+1ENDch07運行環(huán)境22存儲空間分配CNSUME的代碼PRDUCE的代碼靜態(tài)數(shù)據(jù)區(qū)代碼區(qū)CNSUME的活動記錄PRDUCE的活動記錄CHARACTER*50BUFINTEGERNEXTCHARACTERCCHARACTER*80BUFFERINTEGERNEXTch07運行環(huán)境23二、棧式存儲分配存儲空間被組織成棧存儲管理活動開始時,與活動相應的活動記錄入棧,局部變量的存儲空間分配在該活動記錄中。同一過程中聲明的名字在不同的活動中被結(jié)合到不同的存儲空間?;顒咏Y(jié)束時,活動記錄出棧,分配給局部名字的存儲空間被釋放。名字的值將丟失,不可再用。...top...ntopq的活動開始qa...topq的活動結(jié)束ch07運行環(huán)境24programsort(input,output);vara:array[0..10]ofinteger;x:integer;procedurereadarray;vari:integer;beginfori:=1to9doread(a[i])end;prcedureexchange(i,j:integer);beginx:=a[i];a[i]:=a[j];a[j]:=xend;procedurequicksort(m,n:integer);vark,v:integer;functionpartition(y,z:integer):integer;vari,j:integer;begin…a…;…v…;exchange(i,j);end;beginif(n>m)thenbegini:=partition(m,n);quicksort(m,i-1);quicksort(i+1,n)endend{quicksort};begina[0]:=-999;a[10]=999;readarray;quicksort(1,9)end{sort}.對讀入的數(shù)據(jù)進行排序的PASCAL程序ch07運行環(huán)境25控制棧的變化舉例Ssa:arrayx:integerrri:integerq(1,9)p(1,9)=4q(1,9)k:integerv:integerp(1,9)i:integerj:integere(1,9)
q(1,3)q(1,3)k:integerv:integerp(1,3)=1e(1,9)p(1,3)i:integerj:integere(1,3)e(1,3)
q(1,0)q(1,0)k:integerv:integerq(2,3)q(2,3)k:integerv:integerk入棧?出棧?ch07運行環(huán)境26調(diào)用序列除局部數(shù)據(jù)外,活動記錄中還有實現(xiàn)過程調(diào)用和返回的控制信息活動記錄的入棧,實現(xiàn)了控制從調(diào)用過程到被調(diào)用過程的轉(zhuǎn)移控制的轉(zhuǎn)移由一段代碼(即調(diào)用序列)來實現(xiàn)調(diào)用過程p的活動記錄被調(diào)用過程q的活動記錄返回值域參數(shù)域控制鏈訪問鏈機器狀態(tài)域局部數(shù)據(jù)域臨時數(shù)據(jù)域返回值域參數(shù)域控制鏈訪問鏈機器狀態(tài)域局部數(shù)據(jù)域臨時數(shù)據(jù)域top_eptop_sptop_ep
top_sp
PSWtop_sp
ch07運行環(huán)境27調(diào)用序列的安排參數(shù)傳遞:p計算實參的值,寫入q的活動記錄的參數(shù)域;控制信息設(shè)置:p將返回地址寫入q的活動記錄的機器狀態(tài)域中p將當前的top_ep的值寫入q的活動記錄的控制鏈域p為q建立訪問鏈p設(shè)置新的top_ep的值(指向q的活動記錄中某個位置)進入q的代碼(goto語句)q保存寄存器的值、以及其他機器狀態(tài)信息q增加top_sp的值,初始化局部變量開始執(zhí)行ch07運行環(huán)境28返回序列q把返回值寫入自己活動記錄的返回值域q恢復斷點狀態(tài):寄存器的值top_sp和top_ep的值機器狀態(tài)根據(jù)返回地址返回到p的代碼中(goto語句)p把返回值取入自己的活動記錄中p繼續(xù)執(zhí)行ch07運行環(huán)境29調(diào)用序列與活動記錄區(qū)別:活動記錄是一塊連續(xù)的存儲區(qū)域,保存一個活動所需的全部信息,與活動一一對應。調(diào)用序列是一段代碼,完成活動記錄的入棧,實現(xiàn)控制從調(diào)用過程到被調(diào)用過程的轉(zhuǎn)移。調(diào)用序列邏輯上是一個整體,物理上被分成兩部分,分屬于調(diào)用過程和被調(diào)用過程。聯(lián)系:調(diào)用序列的實現(xiàn)與活動記錄中內(nèi)容的安排有密切關(guān)系ch07運行環(huán)境30可變長數(shù)據(jù)的處理某些語言允許由實參的值決定被調(diào)用過程中局部數(shù)組的大小——可變數(shù)組可變數(shù)組的大小只有到執(zhí)行過程調(diào)用時才能確定編譯時可以確定數(shù)組的個數(shù)活動記錄中只設(shè)置相應于可變數(shù)組的指針,而不包括這些數(shù)組的數(shù)據(jù)空間可變數(shù)組的數(shù)據(jù)空間放在活動記錄之外ch07運行環(huán)境31可變數(shù)組的空間分配調(diào)用過程p的活動記錄被調(diào)用過程q的活動記錄返回值域/參數(shù)域控制鏈訪問鏈/機器狀態(tài)域局部/臨時數(shù)據(jù)域top_eptop_sp返回值域/參數(shù)域控制鏈訪問鏈/機器狀態(tài)域局部數(shù)據(jù)域臨時數(shù)據(jù)域pointertoarrayApointertoarrayB數(shù)組A數(shù)組Bch07運行環(huán)境32三、堆式存儲分配如果具體的存儲需求在編譯時刻可以確定——采取靜態(tài)存儲分配策略如果某些存儲需求在編譯時不能確定,但在程序執(zhí)行期間,在程序的入口點上可以知道——采用棧式存儲分配策略棧式存儲分配策略不能處理的存儲需求:程序設(shè)計語言中的某些數(shù)據(jù)結(jié)構(gòu)的存儲需求活動停止時局部名字的值必須被保存下來被調(diào)用過程的活動生存期超過調(diào)用過程的生存期,這種語言的過程間的控制流不能用活動樹正確地描述。共性:活動記錄的釋放不需要遵循先進后出的原則ch07運行環(huán)境33q(1,9)控制鏈堆式存儲分配與棧式存儲分配的比較相同點:動態(tài)存儲分配不同點:組織形式:棧、堆釋放順序:
棧:先進后出
堆:任意Srp(1,9)=4q(1,9)q(1,3)s控制鏈r
控制鏈p(1,9)
控制鏈q(1,3)
控制鏈ch07運行環(huán)境347.3訪問非局部名字一、程序塊二、非嵌套過程的靜態(tài)作用域三、嵌套過程的靜態(tài)作用域四、動態(tài)作用域?qū)Ψ蔷植棵值囊萌Q于作用域規(guī)則靜態(tài)作用域規(guī)則:詞法作用域規(guī)則、最近嵌套規(guī)則動態(tài)作用域規(guī)則:由運行時最近的活動決定可應用到一個名字上的聲明對非局部名字的訪問通過訪問鏈實現(xiàn)關(guān)鍵:訪問鏈如何創(chuàng)建、使用、維護ch07運行環(huán)境35一、程序塊程序塊的基本結(jié)構(gòu)begin聲明語句語句序列end塊可以嵌套塊之間的關(guān)系最近嵌套規(guī)則B1B2B3B4varx,yvarx,avaryvararef.a,x,ych07運行環(huán)境36靜態(tài)作用域舉例main(){inta=0;intb=0;{intb=1;{inta=2;printf(“%d%d\n”,a,b);}{intb=3;printf(“%d%d\n”,a,b);}printf(“%d%d\n”,a,b);}printf(“%d%d\n”,a,b);}B1B2B3B4a=2a=0b=0b=12,10,30,10,0b=3ch07運行環(huán)境37二、非嵌套過程的靜態(tài)作用域過程定義不允許嵌套獨立的順序的聲明語句的位置過程/函數(shù)內(nèi)部所有過程之外在一個過程中引用的名字局部的全局的inta[11];readarray(){…a…}intpartition(inty,intz){…a…}quicksort(intm,intn){inti;…i=partition(m,n);quicksort(m,i-1);quicksort(i+1,n);}main(){readarray;quicksort(0,10);}ch07運行環(huán)境38變量的存儲分配全局變量靜態(tài)地進行分配分配在靜態(tài)數(shù)據(jù)區(qū)中編譯時知道它們的位置,可以將全局變量對應的存儲單元的地址編入目標代碼中局部變量動態(tài)地進行分配分配在活動記錄中棧式存儲分配通過對棧指針的偏移訪問當前活動記錄中的局部名字代碼區(qū)/保存目標代碼靜態(tài)數(shù)據(jù)區(qū)控制棧堆返回值域參數(shù)域控制鏈訪問鏈機器狀態(tài)域局部數(shù)據(jù)域臨時數(shù)據(jù)域top_sptop_epch07運行環(huán)境39過程作為參數(shù)傳遞、作為結(jié)果返回對非局部名字采用靜態(tài)存儲分配前提(源語言)靜態(tài)作用域規(guī)則過程定義不允許嵌套效果一個過程的非局部名,對其他過程也是非局部的非局部名字的存儲空間由編譯程序靜態(tài)地進行分配它的靜態(tài)地址在所有的過程中都可以引用過程對非局部名字的引用與過程是如何激活的無關(guān)結(jié)果無論過程作為參數(shù)傳遞、還是作為結(jié)果返回,其中對非局部名字的引用,都是對靜態(tài)分配給它的存儲單元進行訪問。ch07運行環(huán)境40示例intm;intplusv(intn){returnm+n;}intmulv(intn){returnm*n;}voidcproc(intpform(intn)){cout<<pform(2)<<endl;}voidmain(){m=0;cproc(plusv);cproc(mulv);}pass訪問鏈mcproc<plusv,AL>訪問鏈02220cproc<mulv,AL>訪問鏈mulvn=2訪問鏈00plusvn=2訪問鏈ch07運行環(huán)境41三、嵌套過程的靜態(tài)作用域過程定義允許嵌套最近嵌套規(guī)則Programsort(input,output);vara:array[0..10]ofinteger;x:integer;procedurereadarray;vari:integer;begin…a…end;prcedureexchange(i,j:integer);beginx:=a[i];a[i]:=a[j];a[j]:=xend;procedurequicksort(m,n:integer);vark,v:integer;functionpartition(y,z:integer):integer;vari,j:integer;begin…a…;…v…;exchange(i,j);…end;begin…end{quicksort};begin……end{sort}.ch07運行環(huán)境42過程及名字的嵌套關(guān)系PROCquicksortparam.m,nvark,vFUNpartitionparam.y,zvar.i,jref.a,vcallexchangePROCexchangeparam.i,jref.a,xPROCreadarrayparam.i,jref.a,xvara,x主程序sort嵌套深度主程序:1每進入一個過程,深度加112223名字的嵌套深度聲明時所在過程的嵌套深度ch07運行環(huán)境43訪問鏈被調(diào)用過程活動記錄的訪問鏈指向其直接外層過程的最新活動的活動記錄實現(xiàn)嵌套過程的靜態(tài)作用域規(guī)則通過訪問鏈可以實現(xiàn)對非局部名字的訪問pqpaccessqaccesspqrpaccessraccessqaccessxqprxaccesspaccessraccessqaccessch07運行環(huán)境44訪問鏈的使用過程p引用非局部名字a,嵌套深度分別為np,nana<np當控制處于p中時,p的活動記錄在棧頂訪問鏈的使用從棧頂活動記錄出發(fā),沿訪問鏈前進np-na步到達a的聲明所在過程的最新活動記錄在該活動記錄中,相對于訪問鏈的某個固定偏移處即a的存儲位置該值在編譯時可以計算出來該值在編譯時可以計算出來符號表中,變量名字的目標地址:<嵌套深度,偏移量>p中非局部名字a的地址:<np-na,a在活動記錄中相對于訪問鏈的偏移>ch07運行環(huán)境45訪問鏈的建立在調(diào)用序列中由調(diào)用過程p創(chuàng)建被調(diào)用過程q的訪問鏈過程p和q的嵌套深度分別為np和nqq的活動記錄中訪問鏈的建立依賴于q與p的關(guān)系q嵌套在p中nq>npq不嵌套在p中nq=npnq<npch07運行環(huán)境46q嵌套在p中——nq>np靜態(tài)文本中q與p的關(guān)系:pqnq=np+1paccessqaccessq活動記錄中的訪問鏈指向棧中剛好在其前面的p的活動記錄的訪問鏈調(diào)用序列中,p把base-sp的值寫入q的活動記錄的訪問鏈ch07運行環(huán)境47q不嵌套在p中——nq=np靜態(tài)文本中q與p的關(guān)系:xqpnq=npp和q具有共同的直接外層xaccesspaccessqaccessq活動記錄中的訪問鏈與p的活動記錄的訪問鏈指向棧中剛好在p前面的x的活動記錄訪問鏈調(diào)用序列中,p把自己的訪問鏈的值復制到q的活動記錄的訪問鏈ch07運行環(huán)境48q不嵌套在p中——nq<np靜態(tài)文本中q與p的關(guān)系:rx1x2x3xnp-nqqp......mraccessx1accessxnp-nq-1accessxnp-nqaccess...paccessqaccess從p的活動記錄出發(fā),沿訪問鏈前進np-nq步;指向x1的活動記錄訪問鏈把x1的訪問鏈的值復制到q的活動記錄中訪問鏈域ch07運行環(huán)境49訪問鏈舉例saccessa,xraccessiq(1,9)accessk,vsaccessa,xq(1,9)accessk,vp(1,9)accessi,jq(1,3)accessk,v(a)(b)saccessa,xq(1,9)accessk,vq(1,3)accessk,vp(1,3)accessi,j(c)saccessa,xq(1,9)accessk,vq(1,3)accessk,vp(1,3)accessi,je(1,3)access(d)ch07運行環(huán)境50display表目的:為了提高訪問非局部名字的速度display表:指針數(shù)組d每一個指針指向一個活動記錄d[i]指向嵌套深度為i的過程的最新活動的活動記錄全程數(shù)組元素個數(shù)在編譯時刻根據(jù)過程的最大嵌套深度確定靜態(tài)存儲分配控制棧中,具有相同嵌套深度j的各活動記錄,從靠近棧頂?shù)淖钚禄顒佑涗涢_始,通過訪問鏈鏈成一個鏈表d[j]是該鏈表的頭指針ch07運行環(huán)境51q(1,9)accessk,vd表應用舉例
saccessa,xraccessip(1,9)accessi,jp(1,3)accessi,je(1,3)accessd[3]d[2]d[1]NILsaved[2]NILNILNILNILq(1,3)accessk,vsaved[2]q(1,9)accessk,vsaccessa,xd[3]d[2]d[1]NILNILq(1,3)accessk,vsaccessa,xq(1,9)accessk,vd[3]d[2]d[1]NILNILsaved[2]p(1,3)accessi,jNILq(1,3)accessk,vsaccessa,xq(1,9)accessk,vd[3]d[2]d[1]NILNILsaved[2]ch07運行環(huán)境52四、動態(tài)作用域名字的作用域由程序執(zhí)行過程中,過程之間的調(diào)用與被調(diào)用關(guān)系決定如過程p調(diào)用q,q又調(diào)用rp控制鏈訪問鏈q控制鏈訪問鏈r控制鏈訪問鏈訪問鏈的指向:從被調(diào)用過程指向調(diào)用過程訪問鏈與控制連的指向相同為了訪問非局部名字,可能會沿控制鏈/訪問鏈進入棧的深處——深訪問ch07運行環(huán)境53舉例程序programdy_area(input,output);varr:real;procedureout_val;beginwrite(r:5:3)end;proceduresmall;varr:real;beginr:=1.1;out_valend;beginr:=2.2;out_val;small;writeln;out_val;small;writeln;end.dy_area訪問鏈r靜態(tài)作用域情況2.2out_val訪問鏈2.2small訪問鏈r1.1out_val訪問鏈
2.22.22.2ch07運行環(huán)境54動態(tài)作用域情況dy_area訪問鏈r2.2out_val訪問鏈small訪問鏈r1.1out_val訪問鏈
程序programdy_area(input,output);varr:real;procedureout_val;beginwrite(r:5:3)end;proceduresmall;varr:real;beginr:=1.1;out_valend;beginr:=2.2;out_val;small;writeln;out_val;small;writeln;end.2.21.12.21.1ch07運行環(huán)境55淺訪問方式動態(tài)作用域下,名字可以采用“淺訪問”方式進行存儲分配做法:為每個名字在靜態(tài)分配的存儲空間中保存它的值當控制進入過程p時,p的活動記錄入棧,p中的局部名字a接管靜態(tài)分配給該名字的存儲單元,而將該名字的當前值保存在p的活動記錄中。控制在活動p中時,對名字a的訪問總是對靜態(tài)分配給a的存儲單元進行存取操作。當p的活動結(jié)束時,再用保存的值恢復a的存儲單元。ch07運行環(huán)境567.4參數(shù)傳遞機制一、傳值調(diào)用二、引用調(diào)用三、復制恢復四、傳名調(diào)用過程之間通信的方式:文件非局部名字參數(shù)programreference(input,output);vara,b:integer;procedureswap(x,y:integer);vartemp:integer;begintemp:=x;x:=y;y:=tempend;begina:=1;b:=2;swap(a,b);writeln(
a=
,a);writeln(
b=
,b)end.ch07運行環(huán)境57一、傳值調(diào)用最一般、最簡單的參數(shù)傳遞方法先計算出實參的值,然后將其右值傳遞給被調(diào)用過程,參數(shù)值在過程執(zhí)行時如同常數(shù)。如:有函數(shù)聲明:intmax(intx,inty){returnx>y?x:y;}max(5,3+4):將x替換為5,y替換為7,得到:5>7?5:7。用相應的實參的值替代過程體中出現(xiàn)的所有形參。是C++和Pascal語言的內(nèi)置機制,本質(zhì)上,也是C語言和Java語言參數(shù)傳遞的唯一機制。在這些語言中,參數(shù)被看作是過程的局部變量,初值由調(diào)用時的實參給出。在過程中,參數(shù)和局部變量一樣可以被賦值,但其結(jié)果不影響過程體之外的變量的值。ch07運行環(huán)境58傳值調(diào)用的實現(xiàn)調(diào)用過程對實參求值,并把實參的右值寫入被調(diào)用過程活動記錄的形參存儲單元中。被調(diào)用過程在形參上的操作不影響調(diào)用過程活動記錄中的值referenceab12swapxytemp12121執(zhí)行結(jié)果
a=1b=2ch07運行環(huán)境59參數(shù)是指針類型的情況傳值調(diào)用并不意味著參數(shù)的使用一定不會影響過程體外變量的值。如果參數(shù)的類型為指針或引用,參數(shù)的值就是一個地址通過它可以改變過程體外部的內(nèi)存值。如,有C語言函數(shù)voidinit_ptr(int*p){*p=3;}對參數(shù)p的直接賦值不會改變過程體外的實參的值。如:voidinit_ptr(int*p){p=(int*)malloc(sizeof(int));}在一些語言中,某些值是隱式指針或引用如C語言中的數(shù)組是隱式指針(指向數(shù)組的第一個位置)可以使用數(shù)組參數(shù)來改變存儲在數(shù)組中的值。如:voidinit_array_0(intp[]){p[0]=0;}ch07運行環(huán)境60二、引用調(diào)用原則上要求:實參必須是已經(jīng)分配了存儲空間的變量。調(diào)用過程把一個指向?qū)崊⒋鎯卧闹羔槀鬟f給被調(diào)用過程的相應形參在目標代碼中,被調(diào)用過程通過傳遞給形參的指針間接地引用實參,因此,可以把形參看成是實參的別名,任何對形參的引用就是對相應實參的引用。Fortran語言中唯一的參數(shù)傳遞機制。在Pascal語言中,通過在形參前加關(guān)鍵字var來指定采用引用調(diào)用機制。procedureinc_1(varx:integer);beginx:=x+1end;在C++中,通過在形參的類型關(guān)鍵字后加符號‘&’來指明采用引用調(diào)用機制,如:voidinc_1(int&x){x++;}ch07運行環(huán)境61引用調(diào)用C語言可以通過傳遞引用或顯式指針來實現(xiàn)引用調(diào)用的效果C語言使用‘&’指示變量的地址,使用操作‘*’撤銷引用指針。如:voidinc_1(int*x)//C模擬引用調(diào)用{(*x)++;}……inta;……inc_1(&a);ch07運行環(huán)境62引用調(diào)用的實現(xiàn)調(diào)用過程對實參求值,并把實參的左值寫入被調(diào)用過程活動記錄的形參存儲單元中。若實參是表達式,計算表達式的值,并把它存入臨時存儲單元,然后傳遞這個單元的地址。被調(diào)用過程通過形參間接地引用實參執(zhí)行結(jié)果
a=2b=1referenceab12swapxytemp12
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 濱州學院《通信工程制圖》2023-2024學年第一學期期末試卷
- 濱州學院《機器學習算法與應用》2023-2024學年第一學期期末試卷
- 二零二五年度云計算基礎(chǔ)設(shè)施服務續(xù)簽合同規(guī)范3篇
- 2025版文具及辦公用品共享經(jīng)濟購銷合同2篇
- 2025版軌道交通設(shè)備檢測與維修委托合同范本3篇
- 合同段隧道工程安全專項施工方案
- 2025版金融行業(yè)員工風險管理與聘用協(xié)議2篇
- 二零二五年度LNG運輸事故應急處理與救援合同2篇
- 2024年巨野縣人民醫(yī)院高層次衛(wèi)技人才招聘筆試歷年參考題庫頻考點附帶答案
- 2024年嵩縣中醫(yī)院高層次衛(wèi)技人才招聘筆試歷年參考題庫頻考點附帶答案
- 優(yōu)秀小區(qū)規(guī)劃評析—天津萬科水晶城
- 住宅項目規(guī)范(2022)
- 部編版八年級上全冊古文注釋、翻譯、閱讀習題及答案【2020版】
- 2012生物化學答疑-02
- 公墓項目建議書
- 高壓氧艙技術(shù)要求
- 《怪老頭兒》閱讀測試及答案
- 螺栓對應重量表
- 施工現(xiàn)場消防安全操作規(guī)程
- A4標簽打印模板
- (完整版)工程項目管理組織機構(gòu)
評論
0/150
提交評論