Akagi201的代碼風格
1. 應用代碼和驅動核心代碼風格盡量能夠統一
2. 工程目錄名和檔案名稱為全小寫可以加底線,不用-串連,因為在源碼中變數名不能用-串連,所以要用_方便。如:頂層為:chardevice 或 char_device子目錄為:app dev 或 client server
3. 頂層makefile寫法(待改進,不能make app 這樣單獨編譯)
# Top MakefilePWD = $(shell pwd)all:make -C $(PWD)/appmake -C $(PWD)/devclean:make clean -C $(PWD)/appmake clean -C $(PWD)/dev.PHONY : all clean
4. 未完成,測試驅動的load指令碼 unload指令碼。自動讀取/proc/devices 自動建立裝置節點
5. 標頭檔宏寫法,結合google c++ style和核心以及庫檔案標頭檔寫法。
從工程頂層目錄開始寫,最頂層的工程的目錄名不寫,因為這樣每個開頭都是一樣的沒有區分的意義了。宏的開頭不以底線開始,因為核心和庫的宏好多用底線開頭的,為了區分,我自己定義的宏不以底線開頭。為了區分標頭檔的宏與其他變數的宏,結尾處以底線結尾。後面加個1,可能是為了防止warning把。如
#ifndef APP_GLOBAL_H_#define APP_GLOBAL_H_ 1/////////#endif // APP_GLOBAL_H_
6. 類型命名:變數名_t 如: pthread_t
7. 變數/結構體變數/命名空間命名: 小寫+底線形式 my_exciting_local_variable
8. 結構體類型命名:結構體變數名_t : typedefstruct snd_card snd_card_t;
9. 全域變數: g_,並且儘可能的聲明成static類型,不與其他檔案分享權限設定的全域變數。
10. 盡量杜絕跨檔案訪問全域變數。如果的確需要在多個檔案內訪問同一變數,應該由該變數定義所在檔案內提供 GET/PUT函數實現。即共用全域函數而不是共用全域變數。
11. 全域變數必須要有一個初始值,全域變數盡量放在一個專門的函數內初始化。
12. 全域變數的定義和聲明技巧:利用宏定義實現
// a.h#ifdef AAAint I = 0;#elseextern int I;#endif//a.c 這裡可以定義I,也可以在其他檔案中定義…#include “a.h”#define AAA……//b.c 其他任何檔案中聲明…#include “a.h”….
13. 所有編譯時間常量(無論是局部的、全域的還是類中的)和其他變數保持些許區別,k後接大寫字母開頭的單詞:如:const int kDaysInAWeek = 7;
14. 普通函數命名:因為linux庫函數很多都是小寫單詞_小寫單詞形式如pthread_create()所以為了保持一致,函數命名都統一用小寫+底線形式。
15. 存取函數:存取函數要與存取變數名匹配(小寫+底線形式),此處的小寫函數名意味著可以直接內聯使用
…private: int num_entries_;…void set_num_entries(int num_entries){num_entries_ = num_entries;}
16. 枚舉/宏命名:全部大寫+底線
17. 詞性:除函數名可以適當為動詞外,其他命名盡量使用清晰易懂的名詞。
18. do{}while(0) 的使用
#define 函數名(大寫+底線)(變數列表) do{(用\換行)}while(0)#define DBG_PRINT(fmt, args...) \do \{ \DBG_PRINT_LINE(void); \printk(KERN_ALERT fmt "\n", ## args); \}while(0)// 空的時候也用 do{}while(0)
19. 常用global.h標頭檔
#if defined (__cplusplus) || defined(c_plusplus)extern "C" {#endif // 定義NULL指標#ifndef NULL#if defined (__cplusplus) || defined(c_plusplus)#define NULL 0#else#define NULL ((void *)0)#endif#endif#ifndef TRUE#define TRUE 1#endif#ifndef FALSE#define FALSE 0#endif// 自訂資料類型#ifndef TYPE_UINT8#define TYPE_UINT8typedef unsigned char UINT8;#endif#ifndef TYPE_UINT16#define TYPE_UINT16typedef unsigned short UINT16;#endif#ifndef TYPE_UINT32#define TYPE_UINT32typedef unsigned int UINT32;#endif#ifndef TYPE_INT8#define TYPE_INT8typedef char INT8;#endif#ifndef TYPE_INT16#define TYPE_INT16typedef short INT16;#endif#ifndef TYPE_INT32#define TYPE_INT32typedef int INT32;#endif#ifndef TYPE_FLOAT#define TYPE_FLOATtypedef float FLOAT;#endif#if defined (__cplusplus) || defined(c_plusplus)}#endif
20. 注釋採用doxygen文法格式,結構體和宏注釋用 //>
21. 檔案開頭 #include 先包含庫檔案 #include <庫名> 再包含自己工程中的檔案 #include “檔案名稱”
22. 標頭檔的名字應該與源檔案的名字保持一致。即對應的.h和.c檔案檔案名稱保持一致。
23. C語言人為規定為了區分標頭檔中的函數定義是在對應的.c檔案還是在其他的.c檔案中,這也許不是不許的,因為無論在哪個檔案中定義,聰明的串連程式都能找到。但是,為了方便我們人為地去找標頭檔中某個函數定義的位置,所以要加extern區分,規則如下:
在.h檔案中聲明的函數,如果在其對應的.c檔案中有定義,那麼我們在聲明這個函數時,不使用extern修飾符,如果在其他的.c檔案中定義的,那麼我們要使用extern修飾。
24. 在一個模組檔案中, main函數寫在最前面,函式宣告寫在最開始處,實現放在main函數後面。
25. 公司規定的目錄結構
include :標頭檔目錄,存放*.h檔案。src :定義檔案目錄,存放*.c *.cpp檔案和本目錄內部用的*.h檔案。lib :庫檔案目錄,存放 *.lib和libxxx.a檔案。doc :文檔目錄,存放相關開發文檔。res :資來源目錄,存放圖片檔案、字元檔案、字型檔。integ_test:放在src目錄下的整合測試目錄,存放整合測試相關檔案。test:存放樣本程式和樣本所需要的檔案。
26. 用fprintf 代替 printf
27. 標頭檔中的宏變數都用
#ifndef <宏名>#define <宏名> <宏值>#endif
28. 我自己的列印宏:驅動和應用使用一套列印宏,使用與輸出列印保持一致。ERR_PRINT待改進,介面未統一,另外,沒有加errno 詳見我的share/mystyle/debug.h錯誤捕獲函數:代碼編譯時間完全正確,程式可以運行,沒有成功調用程式中某些系統調用函數而產生的錯誤。往往這些系統調用函數通過傳回值(1-1 0)來說明是否調用成功,而程式員需要知道詳細的錯誤資訊,因此,自建錯誤捕獲函數很有必要。
// 我的列印宏定義#ifdef DEBUG #ifdef __KERNEL__ #define DBG_PRINT_FILE_LINE(void) \ do \ { \ printk(KERN_EMERG "\n%s:%s():%d:", __FILE__, __func__, __LINE__);\ }while (0) #define DBG_PRINT(fmt, args...) \ do \ { \ DEB_PRINT_FILE_LINE(void); \ printk(KERN_EMERG fmt, ##args); \ }while (0) #define ERR_PRINT(fmt, args...) \ do \ { \ printk(KERN_EMERG fmt, ##args); \ }while (0) #else #define DBG_PRINT_FILE_LINE(void) \ do \ { \ fprintf(stderr, "\n%s:%s():%d:", __FILE__, __func__, __LINE__); \ }while (0) #define DBG_PRINT(fmt, args...) \ do \ { \ DBG_PRINT_FILE_LINE(void); fprintf(stderr, fmt, ##args); \ }while (0) #define ERR_PRINT(str) \ do \ { \ DBG_PRINT_FILE_LINE(void); \ perror(str); \ }while (0)#else #define DBG_PRINT_FILE_LINE(void) do{}while (0) #define DBG_PRINT(fmt, args...) do{}while (0) #define ERR_PRINT(fmt, args...) do{}while (0)#endif