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