程式碼閱讀和實踐筆記
高階c資料型別
C指標
c程式中,指標一般用來:
- 構造鏈式資料結構
引用動態分配的資料結構
#define new(type) (type*) calloc(sizeof((type),1) [...] node = new(struct codeword_entry)
實現引用呼叫(call by reference)
訪問和迭代資料元素
傳遞陣列引數
在c和c++程式中,將陣列傳遞到函式和作為結果返回,都要用到指標。在c程式碼中,將陣列名作為函式引數時,實際上傳遞給函式的是陣列第一個元素的地址。因而,函式執行時對陣列中的資料做出的任何修改都將影響到陣列中的元素。
類似函式返回也只是返回陣列的指標。因此當函式在陣列中生成結果並返回相應的指標時,一定要確保該陣列不是在函式的棧上分配的區域性變數。如果陣列是區域性變數要記得確保該陣列不是在函式棧上分配的區域性變數。引用函式
作為其他指的別名
- 效率上的考慮:
- 引用靜態初始化的資料
- 在全域性語境中實現變數引用語義
代表字串
直接訪問系統記憶體
結構
結構還是指向結構的指標?
把指標作為引數的方法的兩個優點:既可以工作在較新的c上,也可以工作較舊的c上;只傳遞一個地址資訊。
缺點:缺少對資料的保護。
把結構作為引數傳遞的一個優點是函式處理的原始資料的副本,這就比直接處理原始資料安全。
- 將一般作為一個整體來使用的資料元素集合到一起
- 從函式中返回多個數據元素
- 構造鏈式資料結構
- 對映資料在硬體裝置、網路連線和儲存介質上的組織方式
- 實現抽象資料型別
以面向物件方式程式設計
可以將資料元素和函式指標聚合成結構,模擬類的欄位和方法,建立與類相仿的實體。struct domain{ int dom_family; char *dom_name; void (*dom_init)(void); [...] int (*dom_rtattach)(void **,int); int dom_rtoffset; int dom_maxrtkey; }; //after init the struct,used like class for(dom = domains;dom;dom = dom -> dom_next){ if(dom -> dom_family == i && dom -> dom_rtattach){ dom -> dom_rtattach((void **)&nep ->ne_rtable[i], dom -> dom_rtoffset); break; } }
實際上,由於同一類別的不同物件共享它們的方法,所以,程式常常在“物件”結構中只儲存指向另外結構的指標。由這個結構給出指向實際方法的指標,從而達到不同物件間共享方法指標的目的。-》面嚮物件語言中的“虛方法”和“多型程式設計”
Union
將共享同一塊儲存區域的項聚合起來。某一時刻,共享該區域的這些項中只有一項可以訪問。
主要用途:
- 有效利用儲存空間
實現多型
多型資料enum msg_type{ CALL = 0; REPLY = 1; };
c資料結構
應對大型專案
設計與實現技術
- 在大型專案中,軟體生命週期的各個組成部分常常被劃分為更小的任務進行處理,它們經常是軟體程式碼庫的一個組成部分。
- 大規模的軟體開發工作必須使用一種合適的架構來構造所要建立的系統。這個架構一般指定系統的結構,控制的處理方式,以及如何對系統各個組成部分進行模組分解。大型的系統還可能會從框架(framework)、設計模式(design pattern)和特定領域的架構中汲取靈感,重用它們架構上的思想。
- 大型系統的複雜性經常可以使用面向物件的設計和實現技術加以控制。一般將物件組織成不同的層次。之後,可以使用繼承來提取出公共行為,動態排程技術使得單一的程式碼體能夠處理眾多不同的物件
- 在更大的粒度上,大型系統的程式碼經常分解為物件模組庫,可重用元件,甚至獨立的程序
- 構建工具

配置
配置(configuration)可以控制的軟體系統,允許開發者編譯、維護和發展原始碼的單一正式版本
根據依賴關係隔離的原則,配置資訊一般分為幾個檔案。影響系統如何編譯的配置資訊(例如,安裝目錄、工具名稱和路徑、是否存在可執行檔案中包括除錯富豪、應用的優化級別、使用的庫和目標檔案),經常以變數定義的形式表示在專案的製作檔案中。
如
修訂控制
我們可以將系統的原始碼想象成在空間和時間兩個方向上的延伸。程式碼,組織成檔案和目錄的形式,佔據空間;同時,同一程式碼還隨著時間的推移不斷演化。
修訂控制--版本控制
測試
設計良好的專案,都會預先為測試系統的全部或部分功能提供相應的措施。這些措施可能隸屬於一份經過深思熟慮,用來驗證系統運作的計劃,也可能是系統的開發者在實現系統的過程中實施的非正式測試活動的殘餘。
最簡單的測試程式碼是一條生成日誌(logging)或除錯(debugging)輸出的語句。跟蹤語句所在的地點一般也是演算法執行的重要部分。
編碼規範和約定
[...]
軟體系統並非知識程式碼。因此,許多編碼指導原則都延伸到開發過程的其他領域,包括文件、生成和釋出過程的組織。
至少,許多指導原則都會規定標準的文件,以及編寫它們的格式。
文件
閱讀一小時程式碼所得到的資訊只不過相當於閱讀一分鐘文件
文件型別
列出幾種最具代表的:
系統規格說明文件:詳細敘述系統的目標、系統的功能需求、管理和技術上的限制、以及成本和日程等要素。通過系統的規格說明文件能夠了解所閱讀程式碼的實際執行環境。
軟體需求規格說明:提供對使用者需求和系統總體構架的高層描述,並且詳細記述系統的功能和非功能性需求,比如資料處理、外部介面、資料庫的邏輯模式以及設計上的各種約束。是閱讀和評估程式碼的基準
設計規格說明:一般描述系統的架構、資料和程式碼結構,還有不同模組之間的介面。面向物件的設計會勾畫出系統的基本型別以及公開方法。細化的設計規格一般還包括每個模組(或類)的具體資訊,比如它執行的具體處理任務、提供的介面,以及與其他模組或類之間的關係。還會描述採用的資料結構,適用的資料庫模式等。認知程式碼結構的路線圖、閱讀具體程式碼的指引
系統的測試規格說明:包括測試計劃、具體的測試過程、以及實際的測試結果。每個測試過程都會詳細說明它所針對的模組以及測試用例使用的資料。
許多使用者文件:功能描述、安裝說明、介紹性的導引、參考手冊和管理員手冊。而且常常是我們唯一有可能獲得的文件。。。在接觸一個未知系統時,功能性的描述和使用者指南可以提供重要的背景資訊,從而更好地理解閱讀程式碼所處的上下文。從使用者參考手冊中,我們可以快速獲取應用程式的外觀與邏輯上的背景知識。從管理員手冊可以得知程式碼的介面、檔案格式和錯誤訊息的詳細資訊。
文件的問題
文件有可能提供不恰當的資訊,誤導我們對原始碼的理解。
系統架構
從系統的原始碼洞悉系統的架構,不是一件容易的事。然而,在識別出重要的架構元素之後,那麼,瀏覽整個系統,瞭解系統的結構和屬性,以及規劃增加、修改和重構活動都會變得更為容易。這是因為,一旦提取出系統的架構行特徵,我們就立即與系統的建立者共享一套語義豐富的詞彙。另外,對系統架構的理解,能夠幫助我們瞭解互動的型別、通訊模式和程式碼結構。
系統的結構
常見、重要的結構可以歸類為少數迥然相異的架構型別:集中式儲存庫(centralized repository)、資料流(data-flow)、面向物件(object-oriented)或分層(layered)架構。
集中式儲存庫:web應用
面向物件:建立在維護自身狀態並相互作用的物件上。系統的架構由不同的類或物件之間的關係,以及物件互動的方式來定義。UML來表達系統的模型。
這關心的層次是系統中的控制流程和資料流。分析系統架構時,可以關注:
- 原始碼在目錄中的安排
- 靜態或動態過程的呼叫
- namespace,package
- 類和介面的繼承關係
- 內部類和巢狀過程
- 異構資料結構和物件關聯中的導航
切片:將程式片(program slice)看作能夠影響變數的值的一段程式。(dashplayer修改原則,我的理解)
控制模型
事件驅動的系統
許多系統中,控制決策通過響應外部生成的事件來完成。(嵌入式開發,關係型資料庫的觸發器)
實現方式可以有許多種:
事件廣播給一系列的事件偵聽者
for(int i = 0;i < list.length;i ++){ ((ContainerListener)list[i]).containerEvent(event); }
硬體中斷
圍繞事件迴圈構建,該迴圈不斷地查詢事件並執行相應的處理
while(XtAppPending(appCtx)) XtAppProcessEvent(appCtx,XtIMALL);
基於類的事件處理給應用程式帶來兩個明顯優點:
* 事件可以以屬性的形式承載附加資訊,消除了無型別、通用的事件引數
* 通過繼承可以實現一個事件層次,事件層次又能夠驅動事件分派策略 ??沒搞懂
下面通過程式碼理據下(反正就這兩句話我是不懂)
public abstract class ArgoEvent extends EventObject implements ArgoEventTypes{
protected int _eventType = 0;
public ArgoEvent(int eventType,Object src){
super(src);
_eventType = eventType;
}
}
//上面的ArgoEvent類擴充套件了Java EventObject,ArgoEvent接下來又被ArgoModuleEvent和ArgoNotationEvent類所擴充套件
系統管理器
需要多個程序併發執行的系統,經常採用系統管理器控制模型。一個單獨的系統元件起到集中式管理器的作用,負責啟動、停止和協調其他系統程序和任務的執行。
狀態變遷

元素封裝
模組和名稱空間
物件是一個執行期間的實體
範型(資料結構或演算法)
抽象資料型別
庫是模組的有組織集合
程序和過濾器(過濾器是一種特殊的程序)
軟體元件(程式構成中典型的自包含單元)(JavaBeans)
架構重用
許多系統在設計時就遵循已經確立的架構。框架
因為可重用的架構,因為要滿足一系列各種各樣的應用程式,所以會比量身定做的應用的結構更為複雜。