嵌入式C语言代码规范
C語言代碼規(guī)范
參考安富萊C語言編碼規(guī)范
1.文件與目錄
1、文件及目錄的命名規(guī)定可用的字符集是[A-Z;a-z;0-9;._-]。
2、源文件名后綴用小寫字母 .c 和.h。
3、文件的命名要準確清晰地表達其內容,同時文件名應該精練,防止文件名過長而造成使用不便。在文件名中可以適當地使用縮寫。
以下提供兩種命名方式以供參考:
4、一個軟件包或一個邏輯組件的所有頭文件和源文件建議放在一個單獨的目錄下,這樣有利于查找并使用相關的文件,有利于簡化一些編譯工具的設置。
5、對于整個項目需要的公共頭文件,應存放在一個單獨的目錄下(例如:myProject/include)下,可避免其他編寫人引用時目錄太過分散的問題。
6、對于源碼文件中的段落安排,我們建議按如下的順序排列:
a. 文件頭注釋 b. 防止重復引用頭文件的設置 c. #include 部分 d. #define 部分 e. enum 常量聲明 f. 類型聲明和定義,包括 struct、union、typedef 等 g. 全局變量聲明 h. 文件級變量聲明 i. 全局或文件級函數聲明 j. 函數實現。按函數聲明的順序排列 k. 文件尾注釋7、在引用頭文件時,使用 <> 來引用預定義或者特定目錄的頭文件,使用 “” 來引用當前目錄或者路徑相對于當前目錄的頭文件。
1 #include <file.h> 執(zhí)行這條指令時,它會在系統(tǒng)目錄中去查找 file.h 文件。在此條碼命令中,不會去當前路徑和附加路徑中查找文件。2 #include "file.h" 執(zhí)行這條指令時,它首先會搜索附加路徑,如果沒有則會搜索系統(tǒng)路徑,如果還沒有則會去搜索當前路徑。8、為了防止頭文件被重復引用,應當用 ifndef/define/endif 結構產生預處理塊。
#ifndef __DISP_H /* 文件名前名加兩個下劃線“__”,后面加 “_H” #define __DISP_H ... ... #endif /* disp.h*/9、頭文件中只存放“聲明”而不存放“定義”,通過這種方式可以避免重復定義。如果其它模塊需要引用全局變量 g_temp, 只需要在文件開頭包含 disp.h
#ifndef __DISP_H /* 文件名前名加兩個下劃線“__”,后面加 “_H” #define __DISP_H /** 全局變量聲明 */ extern uint32_t g_temp; #endif /* disp.h*/ #include "disp.h" /** 全局變量定義 */ uint32_t g_temp = 0;2.排版
1、程序塊要采用縮進風格編寫,縮進的空格數為 4 個。盡量用空格,在不同環(huán)境下Tab鍵代表的空格可能不同,導致排版混亂。
2、相對獨立的程序塊之間、變量說明之后必須加空行增加可讀性、變量最好在使用時在定義。
3、當一行太長時,可以按操作符處劃分新行,劃分出的新行要進行適當的縮進,使排版整齊,語句可讀。
ANO_DT_send_int16((short)(sin(data1/180.0f * PI) * 100),(short)(sin(data2/180.0f * PI) * 100),(short)(sin(data3/180.0f * PI) * 100),(short)(sin(data4/180.0f * PI) * 100), (short)(sin(data5/180.0f * PI) * 100), 0, 0,0);4、不允許把多個短語句寫在一行中,即一行只寫一條語句。
5、程序塊的分界符(如大括號‘{’和‘}’ )應各獨占一行并且位于同一列,同時與引用它們的語句左對齊。在函數體的開始、類的定義、結構的定義、枚舉的定義以及 if、for、do、while、switch、case 語句中的程序都要采用如上的縮進方式。對于與規(guī)則不一致的現存代碼,應優(yōu)先保證同一模塊中的風格一致性。
for (...) { <---- 不規(guī)范的寫法... /* program code */}for (...){ <---- 規(guī)范的寫法... /* program code */}if (...){ <---- 不規(guī)范的寫法... /* program code */}if (...){ <---- 規(guī)范的寫法... /* program code */}6、在兩個以上的關鍵字、變量、常量進行對等操作時,它們之間的操作符之前、之后或者前后要加空格;進行非對等操作時,如果是關系密切的立即操作符(如->),后不應加空格。
說明:采用這種松散方式編寫代碼的目的是使代碼更加清晰。
由于留空格所產生的清晰性是相對的,所以,在已經非常清晰的語句中沒有必要再留空格,如果語句已足夠清晰則括號內側(即左括號后面和右括號前面)不需要加空格,多重括號間不必加空格,因為在 C語言中括號已經是最清晰的標志了。
在長語句中,如果需要加的空格非常多,那么應該保持整體清晰,而在局部不加空格。給操作符留空格時不要連續(xù)留兩個以上空格。
示例:
(1)逗號、分號只在后面加空格。
(2)比較操作符,賦值操作符"="、 “+=”,算術操作符"+"、"%",邏輯操作符"&&"、"&",位域操作符"<<"、"^"等雙目操作符的前后加空格。
if (current_time >= MAX_TIME_VALUE)a = b + c;a *= 2;a = b ^ 2;(3)"!"、"~"、"++"、"–"、"&"(地址運算符)等單目操作符前后不加空格。
*p = 'a'; /* 內容操作"*"與內容之間 */flag = !isEmpty; /* 非操作"!"與內容之間 */p = &mem; /* 地址操作"&" 與內容之間 */i++; /* "++","--"與內容之間 */(4)"->"、"."前后不加空格。
p->id = pid; /* "->"指針前后不加空格 */3.注釋
1、一般情況下,源程序有效注釋量必須在 20%以上。
說明:注釋的原則是有助于對程序的閱讀理解,在該加的地方都加,注釋不宜太多也不能太少,注釋語言必須準確、易懂、簡潔。
2、在文件的開始部分,應該給出關于文件版權、內容簡介、修改歷史等項目的說明。
具體的格式請參見如下的說明。在創(chuàng)建代碼和每次更新代碼時,都必須在文件的歷史記錄中標注版本號、日期、作者、更改說明等項目。
3、對于函數,在函數實現之前,應該給出和函數的實現相關的足夠而精練的注釋信息。內容包括本函數功能介紹,調用的變量、常量說明,形參說明,特別是全局、全程或靜態(tài)變量(慎用靜態(tài)變量),要求對其初值,調用后的預期值作詳細的闡述。具體的書寫格式和包含的各項內容請參見如下的例子。
/*!* @brief ADC通道初始化** @param channel : ADC通道 LQ_ADC.h中的一個枚舉體 * @param bit : ADC通道精度 LQ_ADC.h中的一個枚舉體 ** @return 無** @note 讀取ADC之前一定要調用該函數對ADC通道進行初始化** @see ADC_InitConfig(ADC0CH0_P0_10, ADC_12bit); //初始化ADC通道0 P0_10** @date 2019/10/21 星期一*/ void ADC_InitConfig(ADCn_Ch channel, ADC_nbit bit)對于宏定
/*! CTIMER 最大占空比 可自行修改 */ #define CMTER_PWM_MAX 10000結構體、枚舉體注釋
/** * @brief CTIMER模塊 脈沖計數通道* @note CTIMER 模塊 脈沖捕獲通道 * @note CTIMER 模塊的輸入管腳并不是直接CTIMER連接的 而是通過INPUTMUX模塊連接的* @note CTIMER計數器 --- INPUTMUX輸入多路復用模塊17路通道 ---- 芯片外部管腳* @note 簡單說 就是CTIMER的捕獲通道每個都可以與 INPUTMUX模塊的17路通道相鏈接* @note INPUTMUX模塊的17路通道相鏈接的管腳如下*/ typedef enum {CTInput0_P0_1 = 0x0000 + 1, CTInput0_P0_13 = 0x0000 + 2, /*!< INPUTMUX—CTIMER 輸入通道0管腳 */ CTInput1_P0_14 = 0x0100 + 1, CTInput1_P0_2 = 0x0100 + 2, /*!< INPUTMUX—CTIMER 輸入通道1管腳 */ CTInput2_P1_0 = 0x0200 + 1, CTInput2_P1_28 = 0x0200 + 2, /*!< INPUTMUX—CTIMER 輸入通道2管腳 */ CTInput3_P1_1 = 0x0300 + 1, CTInput3_P1_26 = 0x0300 + 2, /*!< INPUTMUX—CTIMER 輸入通道3管腳 */ CTInput4_P1_9 = 0x0400 + 1, CTInput4_P0_16 = 0x0400 + 2, /*!< INPUTMUX—CTIMER 輸入通道4管腳 */ CTInput5_P1_11 = 0x0500 + 1, /*!< INPUTMUX—CTIMER 輸入通道5管腳 */ CTInput6_P1_13 = 0x0600 + 1, /*!< INPUTMUX—CTIMER 輸入通道6管腳 */ CTInput7_P1_15 = 0x0700 + 1, /*!< INPUTMUX—CTIMER 輸入通道7管腳 */ CTInput8_P0_24 = 0x0800 + 1, /*!< INPUTMUX—CTIMER 輸入通道8管腳 */ CTInput9_P0_25 = 0x0900 + 1, /*!< INPUTMUX—CTIMER 輸入通道9管腳 */ CTInput10_P0_10= 0x0A00 + 1, /*!< INPUTMUX—CTIMER 輸入通道10管腳 */ CTInput11_P0_28= 0x0B00 + 1, /*!< INPUTMUX—CTIMER 輸入通道11管腳 */ CTInput12_P0_4 = 0x0C00 + 1, /*!< INPUTMUX—CTIMER 輸入通道12管腳 */ CTInput13_P0_6 = 0x0D00 + 1, /*!< INPUTMUX—CTIMER 輸入通道13管腳 */ CTInput14_P1_20= 0x0E00 + 1, CTInput14_P0_26= 0x0E00 + 2, /*!< INPUTMUX—CTIMER 輸入通道14管腳 */ CTInput15_P0_20= 0x0F00 + 1, CTInput15_P0_22= 0x0F00 + 2, /*!< INPUTMUX—CTIMER 輸入通道15管腳 */ CTInput16_P0_15= 0x1000 + 1, /*!< INPUTMUX—CTIMER 輸入通道16管腳 */ } CTIMER_InputChannel_t;全局變量
/** DMA link傳輸描述符 */ extern dma_descriptor_t s_dma_descriptor_table0[];注釋應嚴格按以上格式進行注釋,方便日后使用Doxygen生成幫助API文檔
4、邊寫代碼邊注釋,修改代碼同時修改相應的注釋,以保證注釋與代碼的一致性。不再有用的注釋要刪除。
5、注釋的內容要清楚、明了,含義準確,防止注釋二義性。
說明:錯誤的注釋不但無益反而有害。注釋主要闡述代碼做了什么(What),或者如果有必要的話,闡述為什么要這么做(Why),注釋并不是用來闡述它究竟是如何實現算法(How)的。
6、普通注釋格式盡量統(tǒng)一,建議使用“/* …… */”注釋在代碼上方, C++注釋“//”并不被所有 C 編譯器支持。
7、注釋應考慮程序易讀及外觀排版的因素,使用的語言若是中、英兼有的,建議多使用中文,除非能非常流利準確的用英文表達。
8、標識符的命名要清晰、明了,有明確含義,同時使用完整的單詞或大家基本可以理解的縮寫,避免使人產生誤解。
9、命名中若使用特殊約定或縮寫,則要有注釋說明。
10、自己特有的命名風格,要自始至終保持一致,不可來回變化。
11、 對于變量命名,禁止取單個字符(如 i、j、k…),建議除了要有具體含義外,還能表明其變量類型、數據類型等,但 i、j、k 作局部循環(huán)變量是允許的。
12、 除了編譯開關/頭文件等特殊應用,應避免使用_EXAMPLE_TEST_之類以下劃線開始和結尾的定義。
13、除非必要,不要用數字或較奇怪的字符來定義標識符。
4.可讀性
1、注意運算符的優(yōu)先級,并用括號明確表達式的操作順序,避免使用默認優(yōu)先級。
word = (high << 8) | low; if ((a | b) && (a & c)) if ((a | b) < (c & d))2、避免使用不易理解的數字,用有意義的標識來替代。涉及物理狀態(tài)或者含有物理意義的常量,不應直接使用數字,必須用有意義的枚舉或宏來代替。
if (Trunk[index].trunk_state == 0) <---- 不規(guī)范的寫法,應使用有意義的標識 {Trunk[index].trunk_state = 1; <---- 不規(guī)范的寫法,應使用有意義的標識 ... /* program code */} enum trunk_state_e {TRUNK_IDLE = 0,TRUNK_BUSY = 1 };if (Trunk[index].trunk_state == TRUNK_IDLE) {Trunk[index].trunk_state = TRUNK_BUSY; ... /* program code */}3、不要使用難懂的技巧性很高的語句,除非證明改語句是性能瓶頸。
4、為了方便書寫及記憶,變量類型采用如下重定義:
typedef unsigned char uint8_t;typedef unsigned short uint16_t;typedef unsigned long int uint32_t;typedef signed char int8_t;typedef signed short int16_t;typedef signed long int int32_t;#define __IO volatile5、對于一些常見類型的變量,應在其名字前標注表示其類型的前綴。前綴用小寫字母表示。前綴的使用請參照下列表格中說明。
6、變量作用域的前綴
為了清晰的標識變量的作用域,減少發(fā)生命名沖突,應該在變量類型前綴之前再加上表示變量作用域的前綴,并在變量類型前綴和變量作用域前綴之間用下劃線‘-’隔開。
具體的規(guī)則如下:
(1)對于全局變量(global variable),在其名稱前加“g”和變量類型符號前綴。
(2)對于靜態(tài)變量(static variable),在其名稱前加“s”和變量類型符號前綴。
/** 靜態(tài)變量 */ static uint32_t s_ulParaWord;/** 靜態(tài)變量 */ static uint8_t s_ucByte;(3)函數內部等局部變量前不加作用域前綴。
(4)對于常量,當可能發(fā)生作用域和名字沖突問題時,以上幾條規(guī)則對于常量同樣適用。注意,雖然常量名的核心部分全部大寫,但此時常量的前綴仍然用小寫字母,以保持前綴的一致性。
總結
以上是生活随笔為你收集整理的嵌入式C语言代码规范的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 判断是否是2的N次方
- 下一篇: IMXRT10xx MDK 编译器AC5