模組化程式設計技巧

2021-09-29 22:45:22 字數 4161 閱讀 5436

模組化程式設計技巧

提到 c 語言原始檔,大家都不會陌生。因為我們平常寫的程式**幾乎都在這個 xx.c 檔案裡面。編譯器也是以此檔案來進行編譯並生成相應的目標檔案。作為模組化程式設計的組成基礎,我們所要實現的所有功能的源**均在這個檔案裡。在理想的模組化程式設計中,每個模組都可以看成是乙個黑盒子,只需要了解模組提供的功能,不需要關心具體實現該功能的(細節)策略和方法,即提供的是機制而不是策略,機制即功能,策略即方法。好比我們買了一部手機,我們只需要會用手機提供的各種功能即可,至於各種功能在底層是如何實現的使用者不需要關心,這些過程對我們使用者而言,就是乙個黑盒子。

在大規模程式開發中,乙個程式由很多個模組組成,很可能,這些模組的編寫任務被分配到不同的人。而你在編寫這個模組的時候很可能就需要利用到別人寫好的模組的介面,這個時候我們關心的是,它的模組實現了什麼樣的介面,我該如何去呼叫,至於模組內部是如何組織實現的,對於呼叫者而言,無需過多關注。模組對外提供的只是介面,把不需要的細節盡可能對外部遮蔽起來,這正是採用模組化程式設計所需要注意的地方。

乙個模組包含兩個檔案:乙個是「.h」檔案(標頭檔案),另乙個是「.c」檔案。

談及到模組化程式設計,必然會涉及到多檔案編譯,也就是工程編譯。在這樣的乙個系統中,往往會有多個c 檔案,而且每個 c 檔案的作用不盡相同。在我們的 c 檔案中,由於需要對外提供介面,因此必須有一些函式或者是變數提供給外部其它檔案進行呼叫。假設我們有乙個 lcd.c 檔案,其提供最基本的 lcd 的驅動函式

lcdputchar(char cnewvalue) ; //在當前位置輸出乙個字元

而在我們的另外乙個檔案中需要呼叫此函式,那麼我們該如何做呢?

標頭檔案的作用正是在此。可以稱其為乙份介面描述檔案。其檔案內部一般不包含任何實質性的函式**。我們可以把這個標頭檔案理解成為乙份說明書,說明的內容就是我們的模組對外提供的介面函式或者是介面變數。同時該檔案也包含了一些很重要的巨集定義以及一些資料結構的資訊,離開了這些資訊,很可能就無法正常使用介面函式或者是介面變數。標頭檔案基本的構成原則是:不該讓外界知道的資訊就不應該出現在標頭檔案裡,而供外界呼叫的模組介面函式或介面變數所必需的資訊就一定要出現在標頭檔案裡,否則,外界就無法正確的呼叫該模組提供的功能。

因而為了讓外部函式或者檔案呼叫該模組提供的介面函式或變數,就必須包含該模組提供的這個介面描述檔案----「.h」檔案,即標頭檔案。同時,該模組的「.c」檔案也需要包含這個模組標頭檔案(因為它包含了模組原始檔中所需要的巨集定義或資料結構等資訊)

一般來說,標頭檔案的名字應該與原始檔的名字保持一致,這樣我們便可以清晰的知道哪個標頭檔案是哪個原始檔的描述。「

.c」檔案主要功能是對「.h

」檔案中宣告的外部函式進行具體的實現,對具體實現方式沒有特殊規定,只要能實現其函式的功能即可。

於是便得到了 lcd.c 的標頭檔案 lcd.h 其內容如下。

#ifndef _lcd_h_

#define _lcd_h_

extern lcdputchar(char cnewvalue) ;

#endif

這與我們在原始檔中定義函式時有點類似。不同的是,在其前面新增了 extern 修飾符表明其是乙個外部函式,可以被外部其它模組進行呼叫。

#ifndef _lcd_h_

#define _lcd_h_

#endif

這個幾條條件編譯和巨集定義是為了防止重複包含。假如有兩個不同原始檔需要呼叫lcdputchar(char cnewvalue)這個函式,他們分別都通過#include 「lcd.h」把這個標頭檔案包含了進去。在第乙個原始檔進行編譯時候,由於沒有定義過 _lcd_h_ 因此 #ifndef _lcd_h_ 條件成立,於是定義_lcd_h_ 並將下面的宣告包含進去。在第二個檔案編譯時候,由於第乙個檔案包含時候,已經將_lcd_h_定義過了。因此#ifndef _lcd_h_ 不成立,整個標頭檔案內容就沒有被包含。假設沒有這樣的條件編譯語句,那麼兩個檔案都包含了 extern lcdputchar(char cnewvalue) ; 就會引起重複包含的錯誤。

不得不說的

typedef

很多朋友似乎了習慣程式中利用如下語句來對資料型別進行定義

#define uint unsigned int

#define uchar unsigned char

然後在定義變數的時候 直接這樣使用

uint g_ntimecounter = 0 ;

不可否認,這樣確實很方便,而且對於移植起來也有一定的方便性。但是考慮下面這種情況你還會 這麼認為嗎?

#define pint unsigned int * //定義 unsigned int 指標型別

pint g_nptimecounter, g_nptimestate ;

那麼你到底是定義了兩個 unsigned int 型的指標變數,還是乙個指標變數,乙個整形變數呢?而你的初衷又是什麼呢,想定義兩個 unsigned int 型的指標變數嗎?如果是這樣,那麼估計過不久就會到處抓狂找錯誤了。慶幸的是 c 語言已經為我們考慮到了這一點。typedef 正是為此而生。為了給變數起乙個別名我們可以用如下的語句

typedef unsigned int uint16 ; //給指向無符號整形變數起乙個別名 uint16

typedef unsigned int * puint16 ; //給指向無符號整形變數指標起乙個別名 puint16

在我們定義變數時候便可以這樣定義了:

uint16 g_ntimecounter = 0 ; //定義乙個無符號的整形變數

puint16 g_nptimecounter ; //定義乙個無符號的整形變數的指標

在我們使用51微控制器的 c 語言程式設計的時候,整形變數的範圍是16位,而在基於32的微處理下的整形變數是32位。倘若我們在8位微控制器下編寫的一些**想要移植到32位的處理器上,那麼很可能我們就需要在原始檔中到處修改變數的型別定義。這是一件龐大的工作,為了考慮程式的可移植性,在一開始,我們就應該養成良好的習慣,用變數的別名進行定義。

如在8位微控制器的平台下,有如下乙個變數定義

uint16 g_ntimecounter = 0 ;

如果移植32微控制器的平台下,想要其的範圍依舊為16位。

可以直接修改 uint16 的定義,即

typedef unsigned short int uint16 ;

這樣就可以了,而不需要到原始檔處處尋找並修改。

將常用的資料型別全部採用此種方法定義,形成乙個標頭檔案,便於我們以後程式設計直接呼叫。

檔名 macroandconst.h

其內容如下:

#ifndef _macro_and_const_h_

#define _macro_and_const_h_

typedef unsigned int uint16;

typedef unsigned int uint;

typedef unsigned int uint;

typedef unsigned int uint16;

typedef unsigned int word;

typedef unsigned int word;

typedef int int16;

typedef int int16;

typedef unsigned long uint32;

typedef unsigned long uint32;

typedef unsigned long dword;

typedef unsigned long dword;

typedef long int32;

typedef long int32;

typedef signed char int8;

typedef signed char int8;

typedef unsigned char byte;

typedef unsigned char byte;

typedef unsigned char uchar;

typedef unsigned char uint8;

typedef unsigned char uint8;

typedef unsigned char bool;

#endif

至此,似乎我們對於原始檔和標頭檔案的分工以及模組化程式設計有那麼一點概念了。

模組化程式設計

將乙個5元素陣列,右移n位,n從鍵盤輸入,首尾相接 例如 陣列中的元素為 那麼 n 3 的結果如下 資料是向右邊移三位,那麼,我轉化成先移一位的情況。因為當移一位的問題解決了,移動n位只需要將此過程迴圈n次即可 1.把a 1 放到臨時空間t t a 1 2.依次把前面元素的值放到後面的空間裡面.從後...

模組化程式設計小結

模組化程式設計,可以讓程式變得容易理解,結構更加清晰,下面小結一下如何進行模組化程式設計 本文以keil軟體進行舉例 1 將所需要的程式分為 c 和 h 兩類,其中 c 中用來實現程式,h 則用來宣告程式 2 在 c 的檔案中,包含所需的標頭檔案,如 include reg52.h 3 在宣告函式的...

模組化程式設計理解

工作中在做客戶運營系統時,發現js和css的引用還處於最原始的狀態沒有更新。在上乙個專案中通過物件和其中的方法實現了簡單的模組化程式設計。但隨著工程專案的龐大程度增加,簡單的物件已經滿足不了模組化程式設計的需求了,所以接觸了requirejs,了解了amd程式設計規範。和amd對應的是cmd,在no...