




版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、C語(yǔ)言編程要點(diǎn)-第18章 程序的編寫(xiě)和編譯第18章 程序的編寫(xiě)和編譯本章講述在編譯程序時(shí)可以使用的一些技術(shù)。在本章中,你將學(xué)到專業(yè)C程序員在日常編程中所使用的一些技巧。你將會(huì)發(fā)現(xiàn),無(wú)論是對(duì)小項(xiàng)目還是大項(xiàng)目,把源代碼分解成幾個(gè)文件都是很有益處的。在生成函數(shù)庫(kù)時(shí),這一點(diǎn)更為重要。你還將學(xué)到可以使用的各種存儲(chǔ)模式以及怎樣為不同的項(xiàng)目選擇不同的存儲(chǔ)模式。如果你的程序是由幾個(gè)源文件組成的,那么你可以通過(guò)一個(gè)叫MAKE的工具來(lái)管理你的項(xiàng)目(project)。你還將學(xué)到“COM文件和EXE文件的區(qū)別以及使用“COM”文件的一個(gè)好處。 此外,你還將學(xué)到用來(lái)解決一個(gè)典型的DOS問(wèn)題的一些技巧,這個(gè)問(wèn)題就是“沒(méi)有
2、足夠的內(nèi)存來(lái)運(yùn)行DOS程序”。本章還討論了擴(kuò)展內(nèi)存、擴(kuò)充內(nèi)存、磁盤(pán)交換區(qū)、覆蓋管理程序和DOS擴(kuò)展程序的用法,提出了解決RAM阻塞”這一問(wèn)題的多種方法,你可以從中選擇一種最合適的方法18.1. 程序是應(yīng)該寫(xiě)成一個(gè)源文件還是多個(gè)源文件? 如果你的程序確實(shí)很小又很緊湊,那么當(dāng)然應(yīng)該把所有的源代碼寫(xiě)在一個(gè)“C”文件中。然而,如果你發(fā)現(xiàn)自己編寫(xiě)了許多函數(shù)(特別是通用函數(shù)),那么你就應(yīng)該把程序分解成幾個(gè)源文件(也叫做模塊)。 把一個(gè)程序分解成幾個(gè)源文件的過(guò)程叫做模塊化程序設(shè)計(jì)(modular programming)。模塊化程序設(shè)計(jì)技術(shù)提倡用幾個(gè)不同的結(jié)構(gòu)緊湊的模塊一起組成一個(gè)完整的程序。例如,如果一個(gè)
3、程序中有幾種實(shí)用函數(shù)、屏幕函數(shù)和數(shù)據(jù)庫(kù)函數(shù),你就可以把這些函數(shù)分別放在三個(gè)源文件中,分別組成實(shí)用模塊、屏幕模塊和數(shù)據(jù)庫(kù)模塊。 把函數(shù)放在不同的文件中后,你就可以很方便地在其它程序中重復(fù)使用那些通用函數(shù)。如果你有一些函數(shù)還要供其它程序員使用,那么你可以生成一個(gè)與別人共享的函數(shù)庫(kù)(見(jiàn)189)。 你永遠(yuǎn)不必?fù)?dān)心模塊數(shù)目“太多”只要你認(rèn)為合適,你可以生成很多個(gè)模塊。一條好的原則就是保持模塊的緊湊性即在同一個(gè)源文件中只包含那些在邏輯上與其相關(guān)的函數(shù)。如果你發(fā)現(xiàn)自己把幾個(gè)沒(méi)有關(guān)系的函數(shù)放在了同一個(gè)源文件中,那么最好停下來(lái)檢查一下程序的源代碼結(jié)構(gòu),并且對(duì)模塊做一下邏輯上的分解。例如,如果要建立一個(gè)通信管理數(shù)
4、據(jù)庫(kù),你可能需要有這樣一個(gè)模塊結(jié)構(gòu):- 模塊名 內(nèi) 容- Mainc maln()函數(shù) Screenc 屏幕管理函數(shù) Menusc 菜單管理函數(shù) Databasec 數(shù)據(jù)庫(kù)管理函數(shù) Utilityc 通用功能函數(shù) Contactc 通信處理函數(shù) Importc 記錄輸入函數(shù) Exportc 記錄輸出函數(shù) Helpc 聯(lián)機(jī)幫助支持函數(shù)-請(qǐng)參見(jiàn):1810 如果一個(gè)程序包含多個(gè)源文件,怎樣使它們都能正常工作?18.2. 各種存儲(chǔ)模式之間有什么區(qū)別? DOS用一種段地址結(jié)構(gòu)來(lái)編址計(jì)算機(jī)的內(nèi)存,每一個(gè)物理內(nèi)存位置都有一個(gè)可通過(guò)段地址一偏移量的方式來(lái)訪問(wèn)的相關(guān)地址。為了支持這種段地址結(jié)構(gòu),大多數(shù)C編譯程序
5、都允許你用以下6種存儲(chǔ)模式來(lái)創(chuàng)建程序:-存儲(chǔ)模式 限制 所用指針-Tiny(微) 代碼、數(shù)據(jù)和棧一64KB NearSmall(小) 代碼一64KB Near 數(shù)據(jù)和棧一64KB NearMedium(中) 代碼一1MB Far 數(shù)據(jù)和棧一64KB NearCompact(緊縮) 代碼一64KB Near 數(shù)據(jù)和棧一1MB FarLarge(大) 代碼一1MB Far 數(shù)據(jù)和棧一1MB FarHuge*(巨) 代碼一1MB Far 數(shù)據(jù)和棧一1MB Far- *注意:在Huge存儲(chǔ)模式下,靜態(tài)數(shù)據(jù)(如數(shù)組)可以超過(guò)64KB,這在其它存儲(chǔ)模式下都不行。 Tiny存儲(chǔ)模式的限制很?chē)?yán)(所有的代碼、數(shù)
6、據(jù)和棧都被限制在64KB中),它通常用來(lái)生成COM文件。由于內(nèi)存地址的“安排”方式的限制,Huge模式會(huì)帶來(lái)顯著的性能損失,因此它很少被使用。 請(qǐng)參見(jiàn): 183 最常使用的存儲(chǔ)模式有哪些? 184 應(yīng)該使用哪種存儲(chǔ)模式?18.3. 最常使用的存儲(chǔ)模式有哪些? 最常使用的存儲(chǔ)模式有Small,Medium和Large這幾種。Tiny存儲(chǔ)模式一般只用來(lái)生成COM文件,在現(xiàn)在的高性能計(jì)算機(jī)上,它已很少被使用了。Compact存儲(chǔ)模式允許程序有很少的代碼和大量的數(shù)據(jù),在今天的商業(yè)應(yīng)用環(huán)境中,它同樣也不常用了。由于Huge存儲(chǔ)模式的存儲(chǔ)地址機(jī)制導(dǎo)致它的效率較低,所以它也很少被使用。 一般說(shuō)來(lái),你應(yīng)該根據(jù)
7、程序的大小選用Small,Medium或Large中的一種存儲(chǔ)模式。對(duì)一個(gè)小的實(shí)用程序來(lái)說(shuō),Small存儲(chǔ)模式可能是最合適的,這種存儲(chǔ)模式允許有64KB的代碼和64KB數(shù)據(jù)和棧。如果程序有更大一些的數(shù)據(jù)要求,你可以使用Medium存儲(chǔ)模式,它允許程序有多達(dá)1MB的可尋址數(shù)據(jù)空間。對(duì)于更大的程序,你應(yīng)該使用Large存儲(chǔ)模式,它允許程序有1MB的代碼和1MB的數(shù)據(jù)和??臻g。 如果你在編寫(xiě)一個(gè)Windows程序或者在使用一個(gè)32位編譯程序,那么你最好使用Small存儲(chǔ)模式,因?yàn)檫@樣的環(huán)境并不受DOS程序的段地址結(jié)構(gòu)的限制。 請(qǐng)參見(jiàn): 182 各種存儲(chǔ)模式之間有什么區(qū)別? 184 應(yīng)該使用哪種存儲(chǔ)模
8、式?18.4. 應(yīng)該使用哪種存儲(chǔ)模式? 如果要生成一個(gè)“COM”文件,必須使用Tiny存儲(chǔ)模式,即所有的代碼、數(shù)據(jù)和??臻g都被限制在64KB中。小的實(shí)用程序普遍使用這種存儲(chǔ)模式。相對(duì)較小的程序也可以使用Small存儲(chǔ)模式,只不過(guò)不必把整個(gè)程序都限制在64KB中。在Small存儲(chǔ)模式下,有64KB的代碼空間和64KB的數(shù)據(jù)和??臻g。除了用于小程序外,Small存儲(chǔ)模式還可用在Windows或32位編譯程序這樣的環(huán)境中,因?yàn)樵谶@些環(huán)境中內(nèi)存尋址并不受DOS中16位的限制。 如果一個(gè)程序的代碼量相對(duì)較大而靜態(tài)數(shù)據(jù)量相對(duì)較小,你可以用Medium存儲(chǔ)模式來(lái)創(chuàng)建程序。如果程序很大(需要很多模塊,大量的代
9、碼和數(shù)據(jù)),那么你應(yīng)該選用Large存儲(chǔ)模式,這種存儲(chǔ)模式常用在DOS下編寫(xiě)商用軟件。 與Small,Medium和Large存儲(chǔ)模式相比,Compact和Huge存儲(chǔ)模式要少用得多。Cornpact存儲(chǔ)模式允許程序有大量的靜態(tài)數(shù)據(jù)和相對(duì)較少(64KB或更少)的代碼。滿足這種模式的程序很少,常常是一些轉(zhuǎn)移程序,它們有大量必須存到內(nèi)存中的靜態(tài)轉(zhuǎn)移表。Huge存儲(chǔ)模式與Large存儲(chǔ)模式基本相同,只是Huge存儲(chǔ)模式允許程序有超過(guò)64KB的靜態(tài)數(shù)據(jù)。與Compact存儲(chǔ)模式相似,Huge存儲(chǔ)模式也很少被使用,這主要是因?yàn)樗鼤?huì)帶來(lái)顯著的性能損失。由于Huge存儲(chǔ)模式的執(zhí)行效率較低,因此你應(yīng)該避免使用
10、這種模式,除非你確實(shí)需要超過(guò)64KB的一個(gè)數(shù)組或其它靜態(tài)數(shù)據(jù)。記住,數(shù)組和其它程序結(jié)構(gòu)可通過(guò)malloc()和calloc()在程序運(yùn)行時(shí)進(jìn)行動(dòng)態(tài)分配,它們?cè)诒举|(zhì)上并不必須是靜態(tài)的。 請(qǐng)參見(jiàn): 182各種存儲(chǔ)模式之間有什么區(qū)別? 183最常使用的存儲(chǔ)模式有哪些?18.5. 怎樣生成一個(gè)“COM”文件? 生成一個(gè)“COM”文件是指用Tiny存儲(chǔ)模式編譯程序,并用特殊的連接命令產(chǎn)生擴(kuò)展名為COM而不是EXE的文件。記住,如果要使一個(gè)程序成為一個(gè)“COM”文件,那么所有的代碼、數(shù)據(jù)和棧都必須限制在64KB之內(nèi)。這種存儲(chǔ)模式通常只被一些很小的程序使用,例如TSR程序和小的實(shí)用程序。 每個(gè)編譯程序生成“
11、COM”文件的方法都是不同的,你應(yīng)該在編譯程序手冊(cè)中查找有關(guān)信息,以了解哪些編譯選項(xiàng)或連接選項(xiàng)是用來(lái)生成COM文件而不是EXE文件的。 請(qǐng)參見(jiàn): 186“COM”文件有哪些地方優(yōu)于“EXE文件?18.6. “COM”文件有哪些地方優(yōu)于“EXE”文件? 一個(gè)“COM”文件的所有代碼、數(shù)據(jù)和棧都被限制在64KB之內(nèi),因此,它只能用在一些小的應(yīng)用中,例如實(shí)用程序和TSR程序(終止并駐留程序)。“COM”文件的一個(gè)明顯優(yōu)點(diǎn)就是它的裝入要比“EXE文件快得多。 “COM”文件也被稱作“內(nèi)存映象”文件,因?yàn)樗梢灾苯友b入內(nèi)存,不需要任何“處理”?!癊XE文件中包含了由連接程序插入到其它文件頭中的一些特殊的
12、組裝指令,這些指令中包括一個(gè)用來(lái)管理可執(zhí)行程序的不同部分的重定位表?!癈OM”文件中不包含任何這樣的指令或重定位表,因?yàn)檎麄€(gè)程序可以裝入64KB的內(nèi)存空間中。因此,DOS不必去分析任何組裝指令,“COM”文件的裝入速度也就比.EXE文件快。 “COM”文件通常很簡(jiǎn)單,因此它們所能實(shí)現(xiàn)的功能也就受到限制。例如,你不能在“COM”文件中從遠(yuǎn)程堆中分配內(nèi)存。 請(qǐng)參見(jiàn): 185怎樣生成一個(gè)“COM”文件?18.7. 當(dāng)一個(gè)庫(kù)被連接到目標(biāo)上時(shí),庫(kù)中的所有函數(shù)是否都會(huì)被加到一個(gè)EXE文件中? 不會(huì)。當(dāng)啟動(dòng)連接程序時(shí),它會(huì)尋找“未定義的外部函數(shù)”,也就是說(shuō),它將在每一個(gè)庫(kù)文件中查找源代碼文件中未定義的函數(shù)。
13、當(dāng)它找到一個(gè)未定義的外部函數(shù)后,它會(huì)引入包含該函數(shù)定義的目標(biāo)代碼。(obj)。不幸的是,如果這個(gè)函數(shù)是在一個(gè)包含其它函數(shù)定義的源文件中被編譯的話,那么這些函數(shù)也會(huì)被包含進(jìn)來(lái),你的可執(zhí)行代碼中將包含一些不需要的代碼。因此,將庫(kù)函數(shù)放到各自的源文件中是很重要的否則會(huì)浪費(fèi)寶貴的程序空間。有些編譯程序包含特殊的“精明的”連接程序,這些連接程序能查出不需要的函數(shù)并去掉它們,從而使這些函數(shù)不再進(jìn)入你的程序。 下面舉一個(gè)例子:假設(shè)有兩個(gè)源文件,分別為libfunc1c和libfunc2c,它們所包含的函數(shù)都要被放到一個(gè)庫(kù)中。 源文件libfunc1c包含以下兩個(gè)函數(shù): void func_one () .
14、void rune_two() . 源文件libfunc2c包含以下函數(shù): void func_three() . 現(xiàn)在假設(shè)已經(jīng)把這兩個(gè)源文件編譯到一個(gè)名為myfuncs1ib的庫(kù)中。如果一個(gè)與myfuncslib連接的程序要調(diào)用func_one()函數(shù),連接程序就會(huì)在myfuncslib庫(kù)中尋找包含func_one()函數(shù)定義的目標(biāo)代碼,并且把它連接進(jìn)來(lái)。不幸的是,函數(shù)func_one()是在包含func_two()函數(shù)定義的同一個(gè)源文件中被編譯的,因此,即使你的程序不會(huì)用到func_two(),連接程序也不得不把它連接進(jìn)來(lái)。當(dāng)然,這里假設(shè)func_one()中并沒(méi)有包含對(duì)func_two(
15、)的調(diào)用。如果一個(gè)程序包含一個(gè)對(duì)func_three()的調(diào)用,那么只有func_othree()的目標(biāo)代碼會(huì)被連接進(jìn)來(lái),因?yàn)樵摵瘮?shù)是在它自己的源文件中被編譯的。 一般說(shuō)來(lái),你應(yīng)該盡量把庫(kù)函數(shù)放到各自的源文件中。這種組織方式有助于提高程序的效率,因?yàn)槌绦蛑粫?huì)和那些真正需要的函數(shù)進(jìn)行連接,而不會(huì)和那些不需要的函數(shù)進(jìn)行連接。這種組織方式在小組開(kāi)發(fā)的情況下也是很有幫助的;在小組開(kāi)發(fā)中,源文件的上交和發(fā)放非常頻繁,如果一個(gè)程序員要對(duì)一個(gè)包含在其自身的源文件中的函數(shù)進(jìn)行維護(hù),那么他可以集中維護(hù)這個(gè)函數(shù);如果這個(gè)函數(shù)所在的源文件中還包含其它一些需要維護(hù)的函數(shù),那么這些函數(shù)就無(wú)法發(fā)放給其它小組成員,因?yàn)樗鼈?/p>
16、包含在一個(gè)源文件中。 請(qǐng)參見(jiàn): 188 可以把多個(gè)庫(kù)函數(shù)包含在同一個(gè)源文件中嗎? 189 為什么要建立一個(gè)庫(kù)?18.8. 可以把多個(gè)庫(kù)函數(shù)包含在同一個(gè)源文件中嗎? 在同一個(gè)源文件中,你想要定義多少個(gè)函數(shù),就可以定義多個(gè)函數(shù),并且可以把它們都包含到一個(gè)庫(kù)中然而,在小組開(kāi)發(fā)環(huán)境中連接程序和共享源文件時(shí),這種編程風(fēng)格存在著嚴(yán)重的缺陷。 當(dāng)你在一個(gè)源文件中包含多個(gè)庫(kù)函數(shù)時(shí),這些函數(shù)會(huì)被編譯到同一個(gè)目標(biāo)(obj)文件中。當(dāng)連接程序要把其中的一個(gè)函數(shù)連接到程序中去時(shí),目標(biāo)文件中的所有函數(shù)都將被連接進(jìn)來(lái)-不管程序是否用到它們。如果這些函數(shù)是無(wú)關(guān)的(在它們的定義中沒(méi)有相互調(diào)用),那么會(huì)因?yàn)榘巡恍枰拇a連接進(jìn)
17、來(lái)而浪費(fèi)寶貴的程序空間,見(jiàn)187中的例子。這就是要把庫(kù)函數(shù)放到各自的源文件中的原因之一。 另一個(gè)原因是為了在小組開(kāi)發(fā)環(huán)境下便于進(jìn)行代碼共享。使用獨(dú)立的源文件能使小組程序員上交和收回單獨(dú)一個(gè)函數(shù),而不必先鎖住源文件中的一些函數(shù),然后才能修改源文件中的其它函數(shù)。 請(qǐng)參見(jiàn): 187 當(dāng)一個(gè)庫(kù)被連接到目標(biāo)上時(shí),庫(kù)中的所有函數(shù)是否都會(huì)被加到一個(gè)“EXE文件中? 189 為什么要建立一個(gè)庫(kù)?18.9. 為什么要建立一個(gè)庫(kù)? 建立一個(gè)數(shù)據(jù)庫(kù)是為了把可重復(fù)使用的函數(shù)放在一起,供其它程序員和程序共享。例如,你的幾個(gè)程序可能都會(huì)用到一些通用的功能函數(shù),你不必在每個(gè)程序中都復(fù)制這些源代碼,而只需把這些函數(shù)集中到一個(gè)
18、函數(shù)庫(kù)中,然后用連接程序把它們連接到你的程序中去。這種方法有利于程序的維護(hù),因?yàn)槟憧梢栽谝粋€(gè)集中的地方而不是幾個(gè)分散的地方維護(hù)你的函數(shù)。 如果你在小組環(huán)境中工作,那么你應(yīng)該把你的可重復(fù)使用的函數(shù)放到一個(gè)庫(kù)中,這樣其它小組成員就可以把你的函數(shù)連接到他們的程序中去,從而節(jié)省了他們復(fù)制或從頭開(kāi)始寫(xiě)這些函數(shù)的時(shí)間。此外,在一個(gè)包含幾個(gè)模塊的大項(xiàng)目中,可以把那些自始至終都要用到的“框架”支持函數(shù)包含到一個(gè)庫(kù)中。 編譯程序中包含一個(gè)庫(kù)管理器(通常叫做LIBEXE或其它類似的名字),可用來(lái)在函數(shù)庫(kù)中增減目標(biāo)代碼模塊(obj)。有些編譯程序允許你在它們的集成開(kāi)發(fā)環(huán)境中維護(hù)你的庫(kù),而不必人為地啟動(dòng)庫(kù)管理器。無(wú)論
19、如何,你都應(yīng)該參考一下187和188。其中有一些有關(guān)建庫(kù)的重要信息和有用的技巧。 請(qǐng)參見(jiàn): 187 當(dāng)一個(gè)庫(kù)被連接到目標(biāo)上時(shí),庫(kù)中的所有函數(shù)是否都會(huì)被加到一個(gè)“EXE文件中? 188 可以把多個(gè)庫(kù)函數(shù)包含在同一個(gè)源文件中嗎? 建立一個(gè)數(shù)據(jù)庫(kù)是為了把可重復(fù)使用的函數(shù)放在一起,供其它程序員和程序共享。例如,你的幾個(gè)程序可能都會(huì)用到一些通用的功能函數(shù),你不必在每個(gè)程序中都復(fù)制這些源代碼,而只需把這些函數(shù)集中到一個(gè)函數(shù)庫(kù)中,然后用連接程序把它們連接到你的程序中去。這種方法有利于程序的維護(hù),因?yàn)槟憧梢栽谝粋€(gè)集中的地方而不是幾個(gè)分散的地方維護(hù)你的函數(shù)。 如果你在小組環(huán)境中工作,那么你應(yīng)該把你的可重復(fù)使用的
20、函數(shù)放到一個(gè)庫(kù)中,這樣其它小組成員就可以把你的函數(shù)連接到他們的程序中去,從而節(jié)省了他們復(fù)制或從頭開(kāi)始寫(xiě)這些函數(shù)的時(shí)間。此外,在一個(gè)包含幾個(gè)模塊的大項(xiàng)目中,可以把那些自始至終都要用到的“框架”支持函數(shù)包含到一個(gè)庫(kù)中。 編譯程序中包含一個(gè)庫(kù)管理器(通常叫做LIBEXE或其它類似的名字),可用來(lái)在函數(shù)庫(kù)中增減目標(biāo)代碼模塊(obj)。有些編譯程序允許你在它們的集成開(kāi)發(fā)環(huán)境中維護(hù)你的庫(kù),而不必人為地啟動(dòng)庫(kù)管理器。無(wú)論如何,你都應(yīng)該參考一下187和188。其中有一些有關(guān)建庫(kù)的重要信息和有用的技巧。 請(qǐng)參見(jiàn): 187 當(dāng)一個(gè)庫(kù)被連接到目標(biāo)上時(shí),庫(kù)中的所有函數(shù)是否都會(huì)被加到一個(gè)“EXE文件中? 188 可以把
21、多個(gè)庫(kù)函數(shù)包含在同一個(gè)源文件中嗎?18.10. 如果一個(gè)程序包含多個(gè)源文件,怎樣使它們都能正常工作? 編譯程序中包含一個(gè)MAKE工具(通常叫做MAKEEXE,NMAKEEXE或其它類似的名字),其作用是記錄項(xiàng)目以及組成項(xiàng)目的源文件之間的依賴關(guān)系。下面是一個(gè)典型的MAKE文件的例子。myapp. ohj : myapp. c myapp. h cl-c myapp. cutility. obj : utility. c myapp. h cl-c utility. cmyapp, exe : myapp. obj utility. obj cl myapp. obj utility. obj 這
22、個(gè)例子表明myappobj依賴于myappc和myapph,utilityobj依賴于utilityc和myapph,myappexe依賴于myappobj和utilityobj。在表示依賴關(guān)系的每一行下面,都附有一條對(duì)相應(yīng)的目標(biāo)進(jìn)行重新編譯或重新連接的編譯程序命令。例如,myappobj是通過(guò)執(zhí)行下面的命令行重新生成的: cl-c myappc 在上面的例子中,只有在myappc或myapph的時(shí)間標(biāo)志晚于myappobj的時(shí)間標(biāo)志時(shí),myappobj才會(huì)被重新編譯。同樣,只有在utilityc或myapph的時(shí)間標(biāo)志晚于utilityobj的時(shí)間標(biāo)志時(shí),utilityobj才會(huì)被重新編譯;
23、只有在myappobj或utilityobj的時(shí)間標(biāo)志晚于myappexe的時(shí)間標(biāo)志時(shí),myappexe才會(huì)被重新連接。 如果一個(gè)大型項(xiàng)目包含著源文件依賴關(guān)系,那么用MAKE文件來(lái)處理是非常方便的。MAKE工具及其相關(guān)的命令和實(shí)現(xiàn)因編譯程序的不同而不同關(guān)于如何使用MAKE工具,你可以查閱你的編譯程序文檔。 今天,大多數(shù)編譯程序都帶有集成開(kāi)發(fā)環(huán)境,你可以在其中用項(xiàng)目文件來(lái)管理程序中的多個(gè)源文件,如果你有一個(gè)集成環(huán)境,你就不必去了解MAKE工具的復(fù)雜用法,并且可以很方便地管理項(xiàng)目中的源文件,因?yàn)榧森h(huán)境會(huì)為你記錄所有的源文件依賴關(guān)系。 請(qǐng)參見(jiàn): 181程序是應(yīng)該寫(xiě)成一個(gè)源文件還是多個(gè)源文件?18.
24、11. 連接過(guò)程中出現(xiàn)DGROUP:group exceeds 64K消息是怎么回事? 如果在連接時(shí)看到這條出錯(cuò)消息,那是連接程序在指示數(shù)據(jù)(DGROUP)段中的近程數(shù)據(jù)(靜態(tài)數(shù)組元素,全局變量等)超過(guò)了64KB。解決這個(gè)問(wèn)題的辦法有以下幾種: 減少一些全局變量; 減少程序的棧; 用動(dòng)態(tài)存儲(chǔ)分配技術(shù)為數(shù)據(jù)元素分配動(dòng)態(tài)內(nèi)態(tài),而不把它們定義為靜態(tài)型或全局型; 把數(shù)據(jù)元素說(shuō)明為遠(yuǎn)程型而不是近程型。 減少一些全局變量可能要求對(duì)程序的內(nèi)部結(jié)構(gòu)進(jìn)行重新設(shè)計(jì),但這是值得的。從本質(zhì)上講,全局變量的維護(hù)很可能是一場(chǎng)惡夢(mèng),因此只有在確實(shí)需要時(shí)才能使用全局變量。如果你分配了大量的空間作為??臻g,那么你應(yīng)該試試減少棧
25、空間,看看是否能增加可用的內(nèi)存。如果你在程序中使用了大量靜態(tài)數(shù)據(jù),那么你應(yīng)該想辦法重新安排這些靜態(tài)數(shù)據(jù),并且為它們分配動(dòng)態(tài)的而不是靜態(tài)的內(nèi)存。這種技術(shù)可以釋放近程堆,并且使你能從遠(yuǎn)程堆中分配內(nèi)存(見(jiàn)1815中有關(guān)近程堆和遠(yuǎn)程堆的討論)。 請(qǐng)參見(jiàn): 1812 怎樣防止程序用盡內(nèi)存? 1813 如果程序大太而不能在DOS下運(yùn)行,怎樣才能使它在DOS下運(yùn)行呢? 1814 怎樣才能使DOS程序獲得超過(guò)640KB的可用內(nèi)存呢? 1815 近程型(near)和遠(yuǎn)程型(far)的區(qū)別是什么?18.12. 怎術(shù)防止程序用盡內(nèi)存? 如果你使用了大量的靜態(tài)數(shù)據(jù),那么你應(yīng)該考慮使用動(dòng)態(tài)內(nèi)存分配技術(shù)。通過(guò)使用動(dòng)態(tài)內(nèi)存
26、分配技術(shù)(即使用malloc()和calloc()函數(shù)),你可以在需要時(shí)動(dòng)態(tài)地分配內(nèi)存,在不需要時(shí)釋放內(nèi)存。這種方法有幾個(gè)好處:首先,動(dòng)態(tài)內(nèi)存分配技術(shù)會(huì)使程序的效率更高,因?yàn)槌绦蛑辉谛枰獣r(shí)才使用內(nèi)存,并且只使用所需大小的內(nèi)存空間。這樣,靜態(tài)和全局變量就不會(huì)占用大量的空間。其次,你可以通過(guò)檢查malloc()和calloc()函數(shù)的返回值來(lái)掌握內(nèi)存不足的情況。 如果你的程序特別大,你可能要使用覆蓋管理程序或DOS擴(kuò)展程序,或者使用其它內(nèi)存分配機(jī)制,例如EMS和XMS(有關(guān)內(nèi)容見(jiàn)1813和1814)。 請(qǐng)參見(jiàn): 1811連接過(guò)程中出現(xiàn)DGROUP:group exceeds 64K消息是怎么回事?
27、 1813 如果程序太大而不能在DOS下運(yùn)行,怎樣才能使它在DOS下運(yùn)行呢? 1814 怎樣才能使DOS程序獲得超過(guò)640KB的可用內(nèi)存呢? 1815 近程型(near)和遠(yuǎn)程型(far)的區(qū)別是什么?18.13. 如果程序太大而不能在DOS下運(yùn)行,怎樣才能使它在DOS下運(yùn)行呢? 如果你的程序因太大(超過(guò)640KB)而無(wú)法在DOS下運(yùn)行,有兩種辦法可為該程序提供更多的內(nèi)存。一種辦法是使用覆蓋管理程序(overlay manager)。覆蓋管理程序用來(lái)管理程序的模塊,并根據(jù)需要把它們從磁盤(pán)中讀入內(nèi)存或從內(nèi)存中刪去。這樣,即使你的程序有幾兆字節(jié)那么大,仍然可以在只有640KB可用內(nèi)存的計(jì)算機(jī)上運(yùn)行
28、。一些高級(jí)的覆蓋管理程序允許你對(duì)需要同時(shí)讀入和刪除的模塊進(jìn)行“編組”,這有助于你通過(guò)精心調(diào)整程序來(lái)改善它的性能。其它一些稍差的覆蓋管理程序不具備這種功能,因此使用它們時(shí)你無(wú)法通過(guò)編組方式去精心調(diào)整覆蓋模塊。 另一種獲得更多的可用內(nèi)存的辦法是使用DOS擴(kuò)展程序(DOS extender),DOS擴(kuò)展程序是一種特殊的應(yīng)用程序,它通過(guò)使用386,486或更新機(jī)型的保護(hù)模式,按一個(gè)平面地址空間的方式來(lái)存取多達(dá)數(shù)兆字節(jié)的內(nèi)存。當(dāng)你的程序和DOS擴(kuò)展程序連接時(shí),DOS擴(kuò)展程序的代碼將成為該程序的啟動(dòng)代碼的一部分。當(dāng)你的程序被執(zhí)行時(shí),DOS擴(kuò)展程序?qū)⒈谎b入,并且將掌握程序的控制權(quán)。所有的內(nèi)存分配調(diào)用都要通過(guò)
29、DOS擴(kuò)展程序來(lái)進(jìn)行,這樣就跳過(guò)了DOS,而由DOS擴(kuò)展程序來(lái)分配超過(guò)640KB的內(nèi)存。 遺憾的是,DOS擴(kuò)展程序也有一些明顯的缺點(diǎn),其中之一就是,在你發(fā)行你的程序時(shí),大多數(shù)DOS擴(kuò)展程序要求你交納運(yùn)行版稅。這可能非常昂貴,特別是在你有很多用戶時(shí)。也有少數(shù)編譯程序帶有免收版稅的DOS擴(kuò)展程序,但這只不過(guò)是一種例外。使用DOS擴(kuò)展程序的另一個(gè)缺點(diǎn)是它通常要求你通過(guò)修改源代碼而不是通過(guò)DOS調(diào)用來(lái)使用其應(yīng)用編程接口(API)。 覆蓋管理程序一般不要求運(yùn)行費(fèi)用,因此它具有較高的性能價(jià)格比,并且比DOS擴(kuò)展程序更便宜。此外,在使用覆蓋管理程序時(shí),一般不需要修改源代碼,在大多數(shù)情況下,使用覆蓋管理程序?qū)?/p>
30、程序來(lái)說(shuō)是透明的。 請(qǐng)參見(jiàn): 1811 連接過(guò)程中出現(xiàn)DGROUP:group exceeds 64K消息是怎么回事? 1812 怎樣防止程序用盡內(nèi)存? 1814 怎樣才能使DOS程序獲得超過(guò)640KB的可用內(nèi)存呢? 1815 近程型(near)和遠(yuǎn)程型(far)的區(qū)別是什么?18.14. 怎樣才能使DOS程序獲得超過(guò)640KB的可用內(nèi)存呢? 當(dāng)你發(fā)現(xiàn)自己遇到內(nèi)存危機(jī)的情況,需要在DOS程序中使用超過(guò)640KB的內(nèi)存時(shí),你可以用幾種辦法來(lái)獲得更多的可用內(nèi)存。一種辦法是使用磁盤(pán)交換技術(shù)(disk swapping),即把內(nèi)存中不需要的數(shù)據(jù)元素(變量、數(shù)組、結(jié)構(gòu)等)寫(xiě)到磁盤(pán)上,并把它們?cè)瓉?lái)占用的內(nèi)
31、存空間釋放掉(使用free()函數(shù)),從而使程序獲得更多的可用內(nèi)存。當(dāng)需要使用被交換到磁盤(pán)上的數(shù)據(jù)時(shí),你可以把其它不需要的數(shù)據(jù)交換到磁盤(pán)上,然后把要用的數(shù)據(jù)從磁盤(pán)上讀到內(nèi)存中。遺憾的是,這種辦法要求編寫(xiě)大量的代碼,而且實(shí)現(xiàn)起來(lái)比較麻煩。 另一種獲得超過(guò)640KB可用內(nèi)存的辦法是使用其它內(nèi)存資源一EMS(擴(kuò)充內(nèi)存)或XMS(擴(kuò)展內(nèi)存)。EMS和XMS指的是分配640KB區(qū)域以上的內(nèi)存的兩種方法,下文將分別對(duì)其進(jìn)行介紹。 EMS指的是擴(kuò)充內(nèi)存規(guī)范(Expand Memory Specification),它是由Lotus,Intel和Microsoft共同制定的,用來(lái)在IBM兼容機(jī)上訪問(wèn)1MB以上
32、的內(nèi)存區(qū)域。目前該規(guī)范有兩種版本在被使用:LIM32和LIM4O。LIM4O是新的版本,它克服了LIM32的一些局限性。在裝入擴(kuò)充內(nèi)存管理程序(例如DOS中的EMM386EXE)后,你就可以使用擴(kuò)充內(nèi)存了。你的程序可以向擴(kuò)充內(nèi)存管理程序發(fā)出要求使用擴(kuò)充內(nèi)存的請(qǐng)求,擴(kuò)充內(nèi)存管理程序?qū)⑹褂靡环N叫做成組交換(bank switching)的技術(shù),把位于IMB以上區(qū)域中的內(nèi)存暫時(shí)移到640KB和1MB之間的上位內(nèi)存中的一個(gè)空閑區(qū)中。成組交換技術(shù)包括這樣一些內(nèi)容:接受應(yīng)用程序的內(nèi)存分配請(qǐng)求,并通過(guò)每次分配16KB上位內(nèi)存的方式來(lái)映射并管理1MB以上區(qū)域中的內(nèi)存。 擴(kuò)展內(nèi)存在裝入擴(kuò)展內(nèi)存管理程序(例如DO
33、S中的HIMEMSYS)后才會(huì)起作用。你的程序可以向擴(kuò)展內(nèi)存管理程序發(fā)出要求使用擴(kuò)展內(nèi)存塊(EMB)的請(qǐng)求。在申請(qǐng)擴(kuò)展內(nèi)存時(shí),不需要使用“成組交換技術(shù)”,你的程序只需向擴(kuò)展內(nèi)存管理程序發(fā)一個(gè)函數(shù)調(diào)用來(lái)申請(qǐng)一塊位于1MB以上區(qū)域中的內(nèi)存。不幸的是,在DOS下位于1MB以上存儲(chǔ)區(qū)內(nèi)的代碼無(wú)法被執(zhí)行,因此你無(wú)法執(zhí)行在擴(kuò)展內(nèi)存中的代碼。同樣,你也不能直接尋址存在擴(kuò)展內(nèi)存中的數(shù)據(jù),所以,許多程序員喜歡在常規(guī)內(nèi)存(640KB以下)中建立一個(gè)“緩沖區(qū)”,從而為常規(guī)內(nèi)存和擴(kuò)展內(nèi)存提供一個(gè)交換空間。 擴(kuò)充內(nèi)存所使用的技術(shù)比較舊,并且有些過(guò)時(shí)了。當(dāng)基于DOS的帶有擴(kuò)充內(nèi)存的計(jì)算機(jī)剛出現(xiàn)時(shí),擴(kuò)充內(nèi)存的使用極為普遍。
34、使用擴(kuò)充內(nèi)存技術(shù)比使用擴(kuò)展內(nèi)存技術(shù)要慢一些。實(shí)際上,通過(guò)在configsys文件的EMM386EXE設(shè)置項(xiàng)中加入NOEMS標(biāo)志,今天的許多PC機(jī)配置都已完全取消了擴(kuò)充內(nèi)存。大多數(shù)現(xiàn)代程序已經(jīng)放棄了舊的擴(kuò)充內(nèi)存技術(shù),而使用了新的擴(kuò)展內(nèi)存技術(shù)。 如果你的程序要在高于1MB的區(qū)域內(nèi)尋址,你應(yīng)該使用擴(kuò)展內(nèi)存而不是擴(kuò)充內(nèi)存。與使用擴(kuò)充內(nèi)存時(shí)相比,在使用擴(kuò)展內(nèi)存時(shí),你的程序?qū)@得更高的穩(wěn)定性和執(zhí)行速度。 實(shí)現(xiàn)擴(kuò)展內(nèi)存和擴(kuò)充內(nèi)存的具體步驟已超出了本書(shū)的范圍。如果要解釋如何用這些技術(shù)來(lái)訪問(wèn)內(nèi)存,恐怕就要再寫(xiě)一章了。EMS(擴(kuò)充內(nèi)存規(guī)范)和XMS(擴(kuò)展內(nèi)存規(guī)范)文檔可以直接從Mcrosoft公司獲得,也可以從C
35、ompuServe這樣的網(wǎng)絡(luò)服務(wù)器上卸載下來(lái),這些文檔詳細(xì)地介紹了EMS和XMS的應(yīng)用編程接口(API)以及每一項(xiàng)技術(shù)的具體用法。 請(qǐng)參見(jiàn): 1811 連接過(guò)程出現(xiàn)DGROUP:group exceeds 64K消息是怎么回事? 1812 怎樣防止程序用盡內(nèi)存? 1813 如果程序太大而不能在DOS下運(yùn)行,怎樣才能使它在DOS下運(yùn)行呢? 1815 近程型(near)和遠(yuǎn)程型(far)的區(qū)別是什么?18.15. 近程型(near)和遠(yuǎn)程型(far)的區(qū)別是什么? DOS用一種分段結(jié)構(gòu)來(lái)尋址計(jì)算機(jī)的內(nèi)存,每一個(gè)物理存儲(chǔ)位置都有一個(gè)可以用段一偏移量方式來(lái)訪問(wèn)的相關(guān)地址。例如,下面就是一個(gè)典型的段式地
36、址: A000:1234 冒號(hào)左邊的部分代表段地址(A000),冒號(hào)右邊的部分代表相對(duì)于段地址的偏移量。DOS下的每個(gè)程序都是按這種方式訪問(wèn)內(nèi)存的盡管段一偏移量尋址方法的機(jī)理對(duì)大多數(shù)C程序員來(lái)說(shuō)是隱蔽的。 當(dāng)你的程序被執(zhí)行時(shí),一個(gè)存放在數(shù)據(jù)段(DS)寄存器中的數(shù)據(jù)段地址將被賦給你的程序。這個(gè)缺省的數(shù)據(jù)段地址指向一個(gè)64KB的內(nèi)存空間,這個(gè)空間通常就被叫做近程型數(shù)據(jù)段。在這個(gè)近程型數(shù)據(jù)段空間中,你會(huì)找到程序的棧、靜態(tài)數(shù)據(jù)和近程堆。近程堆用來(lái)為程序啟動(dòng)時(shí)所需的全局變量和其它數(shù)據(jù)元素分配內(nèi)存,在這個(gè)空間中分配的任何數(shù)據(jù)都被叫做近程型數(shù)據(jù)。例如,下面的程序在程序啟動(dòng)時(shí)從近程堆中分配了32KB的近程型數(shù)
37、據(jù):/ * Note :Program uses the Medium memory model.* /# include # include # include # include # include void main(void) ;void main(void) char * near_data; near_data= (char * )malloc(32 * 1024) * sizeof(char) ; if (near data= = (char * )NULL) printf(Whoopsie ! Malloc failed! n) ; exit(l) ; strcpy (near_data, This string is going to be. stored in the near heap) ; printf(Address of near_data : %Pn, ,&near_data) ; free (near_data) ; 在上例中,near_data是一個(gè)字符指針,程序分配給它一個(gè)32KB的內(nèi)存塊。在缺省情況下,這個(gè)32KB的內(nèi)存塊是從近程堆中分配的,并且相應(yīng)的16位地址將被存放在字符指針near_data中。 現(xiàn)在,
溫馨提示
- 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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 山西水利職業(yè)技術(shù)學(xué)院《綜合商務(wù)英語(yǔ)技能訓(xùn)練》2023-2024學(xué)年第二學(xué)期期末試卷
- 廣東食品藥品職業(yè)學(xué)院《影視音樂(lè)設(shè)計(jì)制作》2023-2024學(xué)年第二學(xué)期期末試卷
- 湖北財(cái)稅職業(yè)學(xué)院《基礎(chǔ)醫(yī)學(xué)整合案例研討》2023-2024學(xué)年第二學(xué)期期末試卷
- 榆林職業(yè)技術(shù)學(xué)院《熱工基礎(chǔ)及發(fā)動(dòng)機(jī)原理》2023-2024學(xué)年第二學(xué)期期末試卷
- 浙江金華科貿(mào)職業(yè)技術(shù)學(xué)院《酒店員工培訓(xùn)與開(kāi)發(fā)實(shí)訓(xùn)》2023-2024學(xué)年第二學(xué)期期末試卷
- 山東信息職業(yè)技術(shù)學(xué)院《基礎(chǔ)醫(yī)學(xué)整合實(shí)驗(yàn)》2023-2024學(xué)年第二學(xué)期期末試卷
- 太原工業(yè)學(xué)院《項(xiàng)目風(fēng)險(xiǎn)管理》2023-2024學(xué)年第二學(xué)期期末試卷
- 黃岡職業(yè)技術(shù)學(xué)院《田徑理論與實(shí)踐二》2023-2024學(xué)年第二學(xué)期期末試卷
- 西安思源學(xué)院《商務(wù)英語(yǔ)語(yǔ)用學(xué)》2023-2024學(xué)年第二學(xué)期期末試卷
- 廈門(mén)海洋職業(yè)技術(shù)學(xué)院《投資項(xiàng)目評(píng)估》2023-2024學(xué)年第二學(xué)期期末試卷
- 教師禮儀(山東聯(lián)盟)知到智慧樹(shù)章節(jié)測(cè)試課后答案2024年秋山東師范大學(xué)
- 飼料廠粉塵防爆培訓(xùn)課件
- 《田徑運(yùn)動(dòng)課件專題》
- 四川省廣元市劍閣縣市級(jí)名校2025屆中考試題猜想生物試卷含解析(一)
- 華中科技大學(xué)《模擬集成電路設(shè)計(jì)》2023-2024學(xué)年第二學(xué)期期末試卷
- 2024年度海南省國(guó)家電網(wǎng)招聘之電網(wǎng)計(jì)算機(jī)題庫(kù)附答案(典型題)
- (初級(jí))五級(jí)起重裝卸機(jī)械操作工職業(yè)技能鑒定理論考試題庫(kù)(含答案)
- 裂隙燈顯微鏡檢查
- 《新能源乘用車(chē)二手車(chē)鑒定評(píng)估技術(shù)規(guī)范 第1部分:純電動(dòng)》
- 《加坡的教育制度》課件
- 2025年國(guó)家知識(shí)產(chǎn)權(quán)局商標(biāo)審查協(xié)作中心招聘60人高頻重點(diǎn)提升(共500題)附帶答案詳解
評(píng)論
0/150
提交評(píng)論