C語言編程要點-第18章程序的編寫和編譯_第1頁
C語言編程要點-第18章程序的編寫和編譯_第2頁
C語言編程要點-第18章程序的編寫和編譯_第3頁
C語言編程要點-第18章程序的編寫和編譯_第4頁
C語言編程要點-第18章程序的編寫和編譯_第5頁
已閱讀5頁,還剩19頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、C語言編程要點-第18章 程序的編寫和編譯第18章 程序的編寫和編譯本章講述在編譯程序時可以使用的一些技術。在本章中,你將學到專業C程序員在日常編程中所使用的一些技巧。你將會發現,無論是對小項目還是大項目,把源代碼分解成幾個文件都是很有益處的。在生成函數庫時,這一點更為重要。你還將學到可以使用的各種存儲模式以及怎樣為不同的項目選擇不同的存儲模式。如果你的程序是由幾個源文件組成的,那么你可以通過一個叫MAKE的工具來管理你的項目(project)。你還將學到“COM文件和EXE文件的區別以及使用“COM”文件的一個好處。 此外,你還將學到用來解決一個典型的DOS問題的一些技巧,這個問題就是“沒有

2、足夠的內存來運行DOS程序”。本章還討論了擴展內存、擴充內存、磁盤交換區、覆蓋管理程序和DOS擴展程序的用法,提出了解決RAM阻塞”這一問題的多種方法,你可以從中選擇一種最合適的方法18.1. 程序是應該寫成一個源文件還是多個源文件? 如果你的程序確實很小又很緊湊,那么當然應該把所有的源代碼寫在一個“C”文件中。然而,如果你發現自己編寫了許多函數(特別是通用函數),那么你就應該把程序分解成幾個源文件(也叫做模塊)。 把一個程序分解成幾個源文件的過程叫做模塊化程序設計(modular programming)。模塊化程序設計技術提倡用幾個不同的結構緊湊的模塊一起組成一個完整的程序。例如,如果一個

3、程序中有幾種實用函數、屏幕函數和數據庫函數,你就可以把這些函數分別放在三個源文件中,分別組成實用模塊、屏幕模塊和數據庫模塊。 把函數放在不同的文件中后,你就可以很方便地在其它程序中重復使用那些通用函數。如果你有一些函數還要供其它程序員使用,那么你可以生成一個與別人共享的函數庫(見189)。 你永遠不必擔心模塊數目“太多”只要你認為合適,你可以生成很多個模塊。一條好的原則就是保持模塊的緊湊性即在同一個源文件中只包含那些在邏輯上與其相關的函數。如果你發現自己把幾個沒有關系的函數放在了同一個源文件中,那么最好停下來檢查一下程序的源代碼結構,并且對模塊做一下邏輯上的分解。例如,如果要建立一個通信管理數

4、據庫,你可能需要有這樣一個模塊結構:- 模塊名 內 容- Mainc maln()函數 Screenc 屏幕管理函數 Menusc 菜單管理函數 Databasec 數據庫管理函數 Utilityc 通用功能函數 Contactc 通信處理函數 Importc 記錄輸入函數 Exportc 記錄輸出函數 Helpc 聯機幫助支持函數-請參見:1810 如果一個程序包含多個源文件,怎樣使它們都能正常工作?18.2. 各種存儲模式之間有什么區別? DOS用一種段地址結構來編址計算機的內存,每一個物理內存位置都有一個可通過段地址一偏移量的方式來訪問的相關地址。為了支持這種段地址結構,大多數C編譯程序

5、都允許你用以下6種存儲模式來創建程序:-存儲模式 限制 所用指針-Tiny(微) 代碼、數據和棧一64KB NearSmall(小) 代碼一64KB Near 數據和棧一64KB NearMedium(中) 代碼一1MB Far 數據和棧一64KB NearCompact(緊縮) 代碼一64KB Near 數據和棧一1MB FarLarge(大) 代碼一1MB Far 數據和棧一1MB FarHuge*(巨) 代碼一1MB Far 數據和棧一1MB Far- *注意:在Huge存儲模式下,靜態數據(如數組)可以超過64KB,這在其它存儲模式下都不行。 Tiny存儲模式的限制很嚴(所有的代碼、數

6、據和棧都被限制在64KB中),它通常用來生成COM文件。由于內存地址的“安排”方式的限制,Huge模式會帶來顯著的性能損失,因此它很少被使用。 請參見: 183 最常使用的存儲模式有哪些? 184 應該使用哪種存儲模式?18.3. 最常使用的存儲模式有哪些? 最常使用的存儲模式有Small,Medium和Large這幾種。Tiny存儲模式一般只用來生成COM文件,在現在的高性能計算機上,它已很少被使用了。Compact存儲模式允許程序有很少的代碼和大量的數據,在今天的商業應用環境中,它同樣也不常用了。由于Huge存儲模式的存儲地址機制導致它的效率較低,所以它也很少被使用。 一般說來,你應該根據

7、程序的大小選用Small,Medium或Large中的一種存儲模式。對一個小的實用程序來說,Small存儲模式可能是最合適的,這種存儲模式允許有64KB的代碼和64KB數據和棧。如果程序有更大一些的數據要求,你可以使用Medium存儲模式,它允許程序有多達1MB的可尋址數據空間。對于更大的程序,你應該使用Large存儲模式,它允許程序有1MB的代碼和1MB的數據和棧空間。 如果你在編寫一個Windows程序或者在使用一個32位編譯程序,那么你最好使用Small存儲模式,因為這樣的環境并不受DOS程序的段地址結構的限制。 請參見: 182 各種存儲模式之間有什么區別? 184 應該使用哪種存儲模

8、式?18.4. 應該使用哪種存儲模式? 如果要生成一個“COM”文件,必須使用Tiny存儲模式,即所有的代碼、數據和棧空間都被限制在64KB中。小的實用程序普遍使用這種存儲模式。相對較小的程序也可以使用Small存儲模式,只不過不必把整個程序都限制在64KB中。在Small存儲模式下,有64KB的代碼空間和64KB的數據和棧空間。除了用于小程序外,Small存儲模式還可用在Windows或32位編譯程序這樣的環境中,因為在這些環境中內存尋址并不受DOS中16位的限制。 如果一個程序的代碼量相對較大而靜態數據量相對較小,你可以用Medium存儲模式來創建程序。如果程序很大(需要很多模塊,大量的代

9、碼和數據),那么你應該選用Large存儲模式,這種存儲模式常用在DOS下編寫商用軟件。 與Small,Medium和Large存儲模式相比,Compact和Huge存儲模式要少用得多。Cornpact存儲模式允許程序有大量的靜態數據和相對較少(64KB或更少)的代碼。滿足這種模式的程序很少,常常是一些轉移程序,它們有大量必須存到內存中的靜態轉移表。Huge存儲模式與Large存儲模式基本相同,只是Huge存儲模式允許程序有超過64KB的靜態數據。與Compact存儲模式相似,Huge存儲模式也很少被使用,這主要是因為它會帶來顯著的性能損失。由于Huge存儲模式的執行效率較低,因此你應該避免使用

10、這種模式,除非你確實需要超過64KB的一個數組或其它靜態數據。記住,數組和其它程序結構可通過malloc()和calloc()在程序運行時進行動態分配,它們在本質上并不必須是靜態的。 請參見: 182各種存儲模式之間有什么區別? 183最常使用的存儲模式有哪些?18.5. 怎樣生成一個“COM”文件? 生成一個“COM”文件是指用Tiny存儲模式編譯程序,并用特殊的連接命令產生擴展名為COM而不是EXE的文件。記住,如果要使一個程序成為一個“COM”文件,那么所有的代碼、數據和棧都必須限制在64KB之內。這種存儲模式通常只被一些很小的程序使用,例如TSR程序和小的實用程序。 每個編譯程序生成“

11、COM”文件的方法都是不同的,你應該在編譯程序手冊中查找有關信息,以了解哪些編譯選項或連接選項是用來生成COM文件而不是EXE文件的。 請參見: 186“COM”文件有哪些地方優于“EXE文件?18.6. “COM”文件有哪些地方優于“EXE”文件? 一個“COM”文件的所有代碼、數據和棧都被限制在64KB之內,因此,它只能用在一些小的應用中,例如實用程序和TSR程序(終止并駐留程序)。“COM”文件的一個明顯優點就是它的裝入要比“EXE文件快得多。 “COM”文件也被稱作“內存映象”文件,因為它可以直接裝入內存,不需要任何“處理”。“EXE文件中包含了由連接程序插入到其它文件頭中的一些特殊的

12、組裝指令,這些指令中包括一個用來管理可執行程序的不同部分的重定位表。“COM”文件中不包含任何這樣的指令或重定位表,因為整個程序可以裝入64KB的內存空間中。因此,DOS不必去分析任何組裝指令,“COM”文件的裝入速度也就比.EXE文件快。 “COM”文件通常很簡單,因此它們所能實現的功能也就受到限制。例如,你不能在“COM”文件中從遠程堆中分配內存。 請參見: 185怎樣生成一個“COM”文件?18.7. 當一個庫被連接到目標上時,庫中的所有函數是否都會被加到一個EXE文件中? 不會。當啟動連接程序時,它會尋找“未定義的外部函數”,也就是說,它將在每一個庫文件中查找源代碼文件中未定義的函數。

13、當它找到一個未定義的外部函數后,它會引入包含該函數定義的目標代碼。(obj)。不幸的是,如果這個函數是在一個包含其它函數定義的源文件中被編譯的話,那么這些函數也會被包含進來,你的可執行代碼中將包含一些不需要的代碼。因此,將庫函數放到各自的源文件中是很重要的否則會浪費寶貴的程序空間。有些編譯程序包含特殊的“精明的”連接程序,這些連接程序能查出不需要的函數并去掉它們,從而使這些函數不再進入你的程序。 下面舉一個例子:假設有兩個源文件,分別為libfunc1c和libfunc2c,它們所包含的函數都要被放到一個庫中。 源文件libfunc1c包含以下兩個函數: void func_one () .

14、void rune_two() . 源文件libfunc2c包含以下函數: void func_three() . 現在假設已經把這兩個源文件編譯到一個名為myfuncs1ib的庫中。如果一個與myfuncslib連接的程序要調用func_one()函數,連接程序就會在myfuncslib庫中尋找包含func_one()函數定義的目標代碼,并且把它連接進來。不幸的是,函數func_one()是在包含func_two()函數定義的同一個源文件中被編譯的,因此,即使你的程序不會用到func_two(),連接程序也不得不把它連接進來。當然,這里假設func_one()中并沒有包含對func_two(

15、)的調用。如果一個程序包含一個對func_three()的調用,那么只有func_othree()的目標代碼會被連接進來,因為該函數是在它自己的源文件中被編譯的。 一般說來,你應該盡量把庫函數放到各自的源文件中。這種組織方式有助于提高程序的效率,因為程序只會和那些真正需要的函數進行連接,而不會和那些不需要的函數進行連接。這種組織方式在小組開發的情況下也是很有幫助的;在小組開發中,源文件的上交和發放非常頻繁,如果一個程序員要對一個包含在其自身的源文件中的函數進行維護,那么他可以集中維護這個函數;如果這個函數所在的源文件中還包含其它一些需要維護的函數,那么這些函數就無法發放給其它小組成員,因為它們

16、包含在一個源文件中。 請參見: 188 可以把多個庫函數包含在同一個源文件中嗎? 189 為什么要建立一個庫?18.8. 可以把多個庫函數包含在同一個源文件中嗎? 在同一個源文件中,你想要定義多少個函數,就可以定義多個函數,并且可以把它們都包含到一個庫中然而,在小組開發環境中連接程序和共享源文件時,這種編程風格存在著嚴重的缺陷。 當你在一個源文件中包含多個庫函數時,這些函數會被編譯到同一個目標(obj)文件中。當連接程序要把其中的一個函數連接到程序中去時,目標文件中的所有函數都將被連接進來-不管程序是否用到它們。如果這些函數是無關的(在它們的定義中沒有相互調用),那么會因為把不需要的代碼連接進

17、來而浪費寶貴的程序空間,見187中的例子。這就是要把庫函數放到各自的源文件中的原因之一。 另一個原因是為了在小組開發環境下便于進行代碼共享。使用獨立的源文件能使小組程序員上交和收回單獨一個函數,而不必先鎖住源文件中的一些函數,然后才能修改源文件中的其它函數。 請參見: 187 當一個庫被連接到目標上時,庫中的所有函數是否都會被加到一個“EXE文件中? 189 為什么要建立一個庫?18.9. 為什么要建立一個庫? 建立一個數據庫是為了把可重復使用的函數放在一起,供其它程序員和程序共享。例如,你的幾個程序可能都會用到一些通用的功能函數,你不必在每個程序中都復制這些源代碼,而只需把這些函數集中到一個

18、函數庫中,然后用連接程序把它們連接到你的程序中去。這種方法有利于程序的維護,因為你可以在一個集中的地方而不是幾個分散的地方維護你的函數。 如果你在小組環境中工作,那么你應該把你的可重復使用的函數放到一個庫中,這樣其它小組成員就可以把你的函數連接到他們的程序中去,從而節省了他們復制或從頭開始寫這些函數的時間。此外,在一個包含幾個模塊的大項目中,可以把那些自始至終都要用到的“框架”支持函數包含到一個庫中。 編譯程序中包含一個庫管理器(通常叫做LIBEXE或其它類似的名字),可用來在函數庫中增減目標代碼模塊(obj)。有些編譯程序允許你在它們的集成開發環境中維護你的庫,而不必人為地啟動庫管理器。無論

19、如何,你都應該參考一下187和188。其中有一些有關建庫的重要信息和有用的技巧。 請參見: 187 當一個庫被連接到目標上時,庫中的所有函數是否都會被加到一個“EXE文件中? 188 可以把多個庫函數包含在同一個源文件中嗎? 建立一個數據庫是為了把可重復使用的函數放在一起,供其它程序員和程序共享。例如,你的幾個程序可能都會用到一些通用的功能函數,你不必在每個程序中都復制這些源代碼,而只需把這些函數集中到一個函數庫中,然后用連接程序把它們連接到你的程序中去。這種方法有利于程序的維護,因為你可以在一個集中的地方而不是幾個分散的地方維護你的函數。 如果你在小組環境中工作,那么你應該把你的可重復使用的

20、函數放到一個庫中,這樣其它小組成員就可以把你的函數連接到他們的程序中去,從而節省了他們復制或從頭開始寫這些函數的時間。此外,在一個包含幾個模塊的大項目中,可以把那些自始至終都要用到的“框架”支持函數包含到一個庫中。 編譯程序中包含一個庫管理器(通常叫做LIBEXE或其它類似的名字),可用來在函數庫中增減目標代碼模塊(obj)。有些編譯程序允許你在它們的集成開發環境中維護你的庫,而不必人為地啟動庫管理器。無論如何,你都應該參考一下187和188。其中有一些有關建庫的重要信息和有用的技巧。 請參見: 187 當一個庫被連接到目標上時,庫中的所有函數是否都會被加到一個“EXE文件中? 188 可以把

21、多個庫函數包含在同一個源文件中嗎?18.10. 如果一個程序包含多個源文件,怎樣使它們都能正常工作? 編譯程序中包含一個MAKE工具(通常叫做MAKEEXE,NMAKEEXE或其它類似的名字),其作用是記錄項目以及組成項目的源文件之間的依賴關系。下面是一個典型的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、個例子表明myappobj依賴于myappc和myapph,utilityobj依賴于utilityc和myapph,myappexe依賴于myappobj和utilityobj。在表示依賴關系的每一行下面,都附有一條對相應的目標進行重新編譯或重新連接的編譯程序命令。例如,myappobj是通過執行下面的命令行重新生成的: cl-c myappc 在上面的例子中,只有在myappc或myapph的時間標志晚于myappobj的時間標志時,myappobj才會被重新編譯。同樣,只有在utilityc或myapph的時間標志晚于utilityobj的時間標志時,utilityobj才會被重新編譯;

23、只有在myappobj或utilityobj的時間標志晚于myappexe的時間標志時,myappexe才會被重新連接。 如果一個大型項目包含著源文件依賴關系,那么用MAKE文件來處理是非常方便的。MAKE工具及其相關的命令和實現因編譯程序的不同而不同關于如何使用MAKE工具,你可以查閱你的編譯程序文檔。 今天,大多數編譯程序都帶有集成開發環境,你可以在其中用項目文件來管理程序中的多個源文件,如果你有一個集成環境,你就不必去了解MAKE工具的復雜用法,并且可以很方便地管理項目中的源文件,因為集成環境會為你記錄所有的源文件依賴關系。 請參見: 181程序是應該寫成一個源文件還是多個源文件?18.

24、11. 連接過程中出現DGROUP:group exceeds 64K消息是怎么回事? 如果在連接時看到這條出錯消息,那是連接程序在指示數據(DGROUP)段中的近程數據(靜態數組元素,全局變量等)超過了64KB。解決這個問題的辦法有以下幾種: 減少一些全局變量; 減少程序的棧; 用動態存儲分配技術為數據元素分配動態內態,而不把它們定義為靜態型或全局型; 把數據元素說明為遠程型而不是近程型。 減少一些全局變量可能要求對程序的內部結構進行重新設計,但這是值得的。從本質上講,全局變量的維護很可能是一場惡夢,因此只有在確實需要時才能使用全局變量。如果你分配了大量的空間作為棧空間,那么你應該試試減少棧

25、空間,看看是否能增加可用的內存。如果你在程序中使用了大量靜態數據,那么你應該想辦法重新安排這些靜態數據,并且為它們分配動態的而不是靜態的內存。這種技術可以釋放近程堆,并且使你能從遠程堆中分配內存(見1815中有關近程堆和遠程堆的討論)。 請參見: 1812 怎樣防止程序用盡內存? 1813 如果程序大太而不能在DOS下運行,怎樣才能使它在DOS下運行呢? 1814 怎樣才能使DOS程序獲得超過640KB的可用內存呢? 1815 近程型(near)和遠程型(far)的區別是什么?18.12. 怎術防止程序用盡內存? 如果你使用了大量的靜態數據,那么你應該考慮使用動態內存分配技術。通過使用動態內存

26、分配技術(即使用malloc()和calloc()函數),你可以在需要時動態地分配內存,在不需要時釋放內存。這種方法有幾個好處:首先,動態內存分配技術會使程序的效率更高,因為程序只在需要時才使用內存,并且只使用所需大小的內存空間。這樣,靜態和全局變量就不會占用大量的空間。其次,你可以通過檢查malloc()和calloc()函數的返回值來掌握內存不足的情況。 如果你的程序特別大,你可能要使用覆蓋管理程序或DOS擴展程序,或者使用其它內存分配機制,例如EMS和XMS(有關內容見1813和1814)。 請參見: 1811連接過程中出現DGROUP:group exceeds 64K消息是怎么回事?

27、 1813 如果程序太大而不能在DOS下運行,怎樣才能使它在DOS下運行呢? 1814 怎樣才能使DOS程序獲得超過640KB的可用內存呢? 1815 近程型(near)和遠程型(far)的區別是什么?18.13. 如果程序太大而不能在DOS下運行,怎樣才能使它在DOS下運行呢? 如果你的程序因太大(超過640KB)而無法在DOS下運行,有兩種辦法可為該程序提供更多的內存。一種辦法是使用覆蓋管理程序(overlay manager)。覆蓋管理程序用來管理程序的模塊,并根據需要把它們從磁盤中讀入內存或從內存中刪去。這樣,即使你的程序有幾兆字節那么大,仍然可以在只有640KB可用內存的計算機上運行

28、。一些高級的覆蓋管理程序允許你對需要同時讀入和刪除的模塊進行“編組”,這有助于你通過精心調整程序來改善它的性能。其它一些稍差的覆蓋管理程序不具備這種功能,因此使用它們時你無法通過編組方式去精心調整覆蓋模塊。 另一種獲得更多的可用內存的辦法是使用DOS擴展程序(DOS extender),DOS擴展程序是一種特殊的應用程序,它通過使用386,486或更新機型的保護模式,按一個平面地址空間的方式來存取多達數兆字節的內存。當你的程序和DOS擴展程序連接時,DOS擴展程序的代碼將成為該程序的啟動代碼的一部分。當你的程序被執行時,DOS擴展程序將被裝入,并且將掌握程序的控制權。所有的內存分配調用都要通過

29、DOS擴展程序來進行,這樣就跳過了DOS,而由DOS擴展程序來分配超過640KB的內存。 遺憾的是,DOS擴展程序也有一些明顯的缺點,其中之一就是,在你發行你的程序時,大多數DOS擴展程序要求你交納運行版稅。這可能非常昂貴,特別是在你有很多用戶時。也有少數編譯程序帶有免收版稅的DOS擴展程序,但這只不過是一種例外。使用DOS擴展程序的另一個缺點是它通常要求你通過修改源代碼而不是通過DOS調用來使用其應用編程接口(API)。 覆蓋管理程序一般不要求運行費用,因此它具有較高的性能價格比,并且比DOS擴展程序更便宜。此外,在使用覆蓋管理程序時,一般不需要修改源代碼,在大多數情況下,使用覆蓋管理程序對

30、程序來說是透明的。 請參見: 1811 連接過程中出現DGROUP:group exceeds 64K消息是怎么回事? 1812 怎樣防止程序用盡內存? 1814 怎樣才能使DOS程序獲得超過640KB的可用內存呢? 1815 近程型(near)和遠程型(far)的區別是什么?18.14. 怎樣才能使DOS程序獲得超過640KB的可用內存呢? 當你發現自己遇到內存危機的情況,需要在DOS程序中使用超過640KB的內存時,你可以用幾種辦法來獲得更多的可用內存。一種辦法是使用磁盤交換技術(disk swapping),即把內存中不需要的數據元素(變量、數組、結構等)寫到磁盤上,并把它們原來占用的內

31、存空間釋放掉(使用free()函數),從而使程序獲得更多的可用內存。當需要使用被交換到磁盤上的數據時,你可以把其它不需要的數據交換到磁盤上,然后把要用的數據從磁盤上讀到內存中。遺憾的是,這種辦法要求編寫大量的代碼,而且實現起來比較麻煩。 另一種獲得超過640KB可用內存的辦法是使用其它內存資源一EMS(擴充內存)或XMS(擴展內存)。EMS和XMS指的是分配640KB區域以上的內存的兩種方法,下文將分別對其進行介紹。 EMS指的是擴充內存規范(Expand Memory Specification),它是由Lotus,Intel和Microsoft共同制定的,用來在IBM兼容機上訪問1MB以上

32、的內存區域。目前該規范有兩種版本在被使用:LIM32和LIM4O。LIM4O是新的版本,它克服了LIM32的一些局限性。在裝入擴充內存管理程序(例如DOS中的EMM386EXE)后,你就可以使用擴充內存了。你的程序可以向擴充內存管理程序發出要求使用擴充內存的請求,擴充內存管理程序將使用一種叫做成組交換(bank switching)的技術,把位于IMB以上區域中的內存暫時移到640KB和1MB之間的上位內存中的一個空閑區中。成組交換技術包括這樣一些內容:接受應用程序的內存分配請求,并通過每次分配16KB上位內存的方式來映射并管理1MB以上區域中的內存。 擴展內存在裝入擴展內存管理程序(例如DO

33、S中的HIMEMSYS)后才會起作用。你的程序可以向擴展內存管理程序發出要求使用擴展內存塊(EMB)的請求。在申請擴展內存時,不需要使用“成組交換技術”,你的程序只需向擴展內存管理程序發一個函數調用來申請一塊位于1MB以上區域中的內存。不幸的是,在DOS下位于1MB以上存儲區內的代碼無法被執行,因此你無法執行在擴展內存中的代碼。同樣,你也不能直接尋址存在擴展內存中的數據,所以,許多程序員喜歡在常規內存(640KB以下)中建立一個“緩沖區”,從而為常規內存和擴展內存提供一個交換空間。 擴充內存所使用的技術比較舊,并且有些過時了。當基于DOS的帶有擴充內存的計算機剛出現時,擴充內存的使用極為普遍。

34、使用擴充內存技術比使用擴展內存技術要慢一些。實際上,通過在configsys文件的EMM386EXE設置項中加入NOEMS標志,今天的許多PC機配置都已完全取消了擴充內存。大多數現代程序已經放棄了舊的擴充內存技術,而使用了新的擴展內存技術。 如果你的程序要在高于1MB的區域內尋址,你應該使用擴展內存而不是擴充內存。與使用擴充內存時相比,在使用擴展內存時,你的程序將獲得更高的穩定性和執行速度。 實現擴展內存和擴充內存的具體步驟已超出了本書的范圍。如果要解釋如何用這些技術來訪問內存,恐怕就要再寫一章了。EMS(擴充內存規范)和XMS(擴展內存規范)文檔可以直接從Mcrosoft公司獲得,也可以從C

35、ompuServe這樣的網絡服務器上卸載下來,這些文檔詳細地介紹了EMS和XMS的應用編程接口(API)以及每一項技術的具體用法。 請參見: 1811 連接過程出現DGROUP:group exceeds 64K消息是怎么回事? 1812 怎樣防止程序用盡內存? 1813 如果程序太大而不能在DOS下運行,怎樣才能使它在DOS下運行呢? 1815 近程型(near)和遠程型(far)的區別是什么?18.15. 近程型(near)和遠程型(far)的區別是什么? DOS用一種分段結構來尋址計算機的內存,每一個物理存儲位置都有一個可以用段一偏移量方式來訪問的相關地址。例如,下面就是一個典型的段式地

36、址: A000:1234 冒號左邊的部分代表段地址(A000),冒號右邊的部分代表相對于段地址的偏移量。DOS下的每個程序都是按這種方式訪問內存的盡管段一偏移量尋址方法的機理對大多數C程序員來說是隱蔽的。 當你的程序被執行時,一個存放在數據段(DS)寄存器中的數據段地址將被賦給你的程序。這個缺省的數據段地址指向一個64KB的內存空間,這個空間通常就被叫做近程型數據段。在這個近程型數據段空間中,你會找到程序的棧、靜態數據和近程堆。近程堆用來為程序啟動時所需的全局變量和其它數據元素分配內存,在這個空間中分配的任何數據都被叫做近程型數據。例如,下面的程序在程序啟動時從近程堆中分配了32KB的近程型數

37、據:/ * 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是一個字符指針,程序分配給它一個32KB的內存塊。在缺省情況下,這個32KB的內存塊是從近程堆中分配的,并且相應的16位地址將被存放在字符指針near_data中。 現在,

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論