一個(gè)優(yōu)秀的項(xiàng)目,必定有優(yōu)秀的“基因”,而編碼規(guī)范就是其中之一。
之前給大家分享過很多關(guān)于編碼規(guī)范的內(nèi)容,今年分享一下RT-Thread的編碼規(guī)范。
RT-Thread 編程風(fēng)格
這是一份 RT-Thread 開發(fā)人員的開發(fā)指引。RT-Thread 做為一份開源軟件,它需要由不同的人采用合作的方式完成,這份文檔是開發(fā)人員的一個(gè)指引。RT-Thread 的開發(fā)人員請遵守這樣的編程風(fēng)格。同時(shí)對于使用 RT-Thread 的用戶,也可通過這份文檔了解 RT-Thread代碼內(nèi)部一些約定從而比較容易的把握到 RT-Thread 的實(shí)現(xiàn)方式。
1.目錄名稱
目錄名稱如果無特殊的需求,請使用全小寫的形式;目錄名稱應(yīng)能夠反映部分的意思,例如各芯片移植由其芯片名稱構(gòu)成或芯片類別構(gòu)成;components 目錄下能夠反映組件的意義。
2.文件名稱
文件名稱如果無特殊的需求(如果是引用其他地方,可以保留相應(yīng)的名稱),請使用全小寫的形式。另外為了避免文件名重名的問題,一些地方請盡量不要使用通用化、使用頻率高的名稱。
設(shè)備驅(qū)動源碼文件:drv_class.c的命名方式,如:
-
drv_spi.c
-
drv_gpio.c
3.頭文件定義
C 語言頭文件為了避免多次重復(fù)包含,需要定義一個(gè)符號。這個(gè)符號的定義形式請采用如下的風(fēng)格:
1#ifndef__FILE_H__
2#define__FILE_H__
3/*headerfilecontent*/
4#endif
即定義的符號兩側(cè)采用 “__” 以避免重名,另外也可以根據(jù)文件名中是否包含多個(gè)詞語而采用 “_” 連接起來。
4.文件頭注釋
在每個(gè)源文件文件頭上,應(yīng)該包括相應(yīng)的版權(quán)信息,Change Log 記錄:
1/*
2*Copyright(c)2006-2020,RT-ThreadDevelopmentTeam
3*
4*SPDX-License-Identifier:Apache-2.0
5*
6*ChangeLogs:
7*DateAuthorNotes
8*2006-03-18Bernardthefirstversion
9*2006-04-26BernardaddsemaphoreAPIs
10*/
例如采用如上的形式。
5.結(jié)構(gòu)體定義
結(jié)構(gòu)體名稱請使用小寫英文名的形式,單詞與單詞之間采用 “_” 連接,例如:
1structrt_list_node
2{
3structrt_list_node*next;
4structrt_list_node*prev;
5};
其中,"{","}" 獨(dú)立占用一行,后面的成員定義使用縮進(jìn)的方式定義。
結(jié)構(gòu)體等的類型定義請以結(jié)構(gòu)體名稱加上 “_t” 的形式作為名稱,例如:
1typedefstructrt_list_nodert_list_t;
因?yàn)閮?nèi)核中對象引用方便的緣故,采用了對象內(nèi)核指針作為類型定義的形式,例如:
1typedefstructrt_timer*rt_timer_t;
6.宏定義
在RT-Thread中,請使用大寫英文名稱作為宏定義,單詞之間使用 “_” 連接,例如:
1#defineRT_TRUE1
7.函數(shù)名稱、聲明
函數(shù)名稱請使用小寫英文的形式,單詞之間使用 “_” 連接。提供給上層應(yīng)用使用的 API接口,必須在相應(yīng)的頭文件中聲明;如果函數(shù)入口參數(shù)是空,必須使用 void 作為入口參數(shù),例如:
1rt_thread_trt_thread_self(void);
內(nèi)部靜態(tài)函數(shù)命名:以下劃線開頭,使用_class_method格式,不攜帶_rt_開頭,如內(nèi)核或驅(qū)動文件中的函數(shù)命名:
1/*IPCobjectinit*/
2staticrt_err_t_ipc_object_init()
3
4/*UARTdriverops*/
5staticrt_err_t_uart_configure()
6staticrt_err_t_uart_control()
調(diào)用注冊設(shè)備接口的函數(shù)命名:使用rt_hw_class_init()格式,舉例:
1intrt_hw_uart_init(void)
2intrt_hw_spi_init(void)
8.注釋編寫
請使用英文做為注釋,使用中文注釋將意味著在編寫代碼時(shí)需要來回不停的切換中英文輸入法從而打斷編寫代碼的思路。并且使用英文注釋也能夠比較好的與中國以外的技術(shù)者進(jìn)行交流。
語句注釋:
源代碼的注釋不應(yīng)該過多,更多的說明應(yīng)該是代碼做了什么,僅當(dāng)個(gè)別關(guān)鍵點(diǎn)才需要一些相應(yīng)提示性的注釋以解釋一段復(fù)雜的算法它是如何工作的。對語句的注釋只能寫在它的上方或右方,其他位置都是非法的。
1/*你的英文注釋*/
函數(shù)注釋:
注釋以/**開頭,以*/結(jié)尾,中間寫入函數(shù)注釋,組成元素如下,每個(gè)元素描述之間空一行,且首列對齊:
-
@brief + 簡述函數(shù)作用。在描述中,著重說明該函數(shù)的作用,每句話首字母大寫,句尾加英文句號。
-
@note + 函數(shù)說明。在上述簡述中未能體現(xiàn)到的函數(shù)功能或作用的一些點(diǎn),可以做解釋說明,每句話首字母大寫,句尾加英文句號。
-
@see + 相關(guān) API 羅列。若有與當(dāng)前函數(shù)相關(guān)度較高的 API,可以進(jìn)行列舉。
-
@param + 以參數(shù)為主語 + be 動詞 + 描述,說明參數(shù)的意義或來源。
-
@return + 枚舉返回值 + 返回值的意思,若返回值為數(shù)據(jù),則直接介紹數(shù)據(jù)的功能。
-
@warning + 函數(shù)使用注意要點(diǎn)。在函數(shù)使用時(shí),描述需要注意的事項(xiàng),如使用環(huán)境、使用方式等。每句話首字母大寫,句尾加英文句號。
注釋模版請參見:rt-thread/src/ipc.c 源碼文件,英文注釋請參考使用 grammarly 以及谷歌翻譯。
1/**
2*@briefThefunctionwillinitializeastaticeventobject.
3*
4*@noteForthestaticeventobject,itsmemoryspaceisallocatedbythecompilerduringcompiling,
5*andshallplacedontheread-writedatasegmentorontheuninitializeddatasegment.
6*Bycontrast,thert_event_create()functionwillallocatememoryspaceautomatically
7*andinitializetheevent.
8*
9*@seert_event_create()
10*
11*@parameventisapointertotheeventtoinitialize.Itisassumedthatstoragefortheevent
12*willbeallocatedinyourapplication.
13*
14*@paramnameisapointertothenamethatgiventotheevent.
15*
16*@paramvalueistheinitialvaluefortheevent.
17*Ifwanttoshareresources,youshouldinitializethevalueasthenumberofavailableresources.
18*Ifwanttosignaltheoccurrenceofanevent,youshouldinitializethevalueas0.
19*
20*@paramflagistheeventflag,whichdeterminesthequeuingwayofhowmultiplethreadswait
21*whentheeventisnotavailable.
22*TheeventflagcanbeONEofthefollowingvalues:
23*
24*RT_IPC_FLAG_PRIOThependingthreadswillqueueinorderofpriority.
25*
26*RT_IPC_FLAG_FIFOThependingthreadswillqueueinthefirst-in-first-outmethod
27*(alsoknownasfirst-come-first-served(FCFS)schedulingstrategy).
28*
29*NOTE:RT_IPC_FLAG_FIFOisanon-real-timeschedulingmode.Itisstronglyrecommendedto
30*useRT_IPC_FLAG_PRIOtoensurethethreadisreal-timeUNLESSyourapplicationsconcernabout
31*thefirst-in-first-outprinciple,andyouclearlyunderstandthatallthreadsinvolvedin
32*thiseventwillbecomenon-real-timethreads.
33*
34*@returnReturntheoperationstatus.WhenthereturnvalueisRT_EOK,theinitializationissuccessful.
35*Ifthereturnvalueisanyothervalues,itrepresentstheinitializationfailed.
36*
37*@warningThisfunctioncanONLYbecalledfromthreads.
38*/
39rt_err_trt_event_init(rt_event_tevent,constchar*name,rt_uint8_tflag)
40{
41...
42}
9.縮進(jìn)及分行
縮進(jìn)請采用 4 個(gè)空格的方式。如果沒有什么特殊意義,請?jiān)?“{” 后進(jìn)行分行,并在下一行都采用縮進(jìn)的方式,例如:
1if(condition)
2{
3/*others*/
4}
唯一的例外是 switch 語句,switch-case 語句采用 case 語句與 switch 對齊的方式,例如:
1switch(value)
2{
3casevalue1:
4break;
5}
case 語句與前面的 switch 語句對齊,后續(xù)的語句則采用縮進(jìn)的方式。分行上,如果沒有什么特殊考慮,請不要在代碼中連續(xù)使用兩個(gè)以上的空行。
10.大括號與空格
從代碼閱讀角度,建議每個(gè)大括號單獨(dú)占用一行,而不是跟在語句的后面,例如:
1if(condition)
2{
3/*others*/
4}
匹配的大括號單獨(dú)占用一行,代碼閱讀起來就會有相應(yīng)的層次而不會容易出現(xiàn)混淆的情況??崭窠ㄗh在非函數(shù)方式的括號調(diào)用前留一個(gè)空格以和前面的進(jìn)行區(qū)分,例如:
1if(x<=?y)
2{
3/*others*/
4}
5
6for(index=0;index7{
8/*others*/
9}
建議在括號前留出一個(gè)空格(涉及的包括 if、for、while、switch 語句),而運(yùn)算表達(dá)式中,運(yùn)算符與字符串間留一個(gè)空格。另外,不要在括號的表達(dá)式兩側(cè)留空格,例如:
1if(x<=?y?)
2{
3/*other*/
4}
這樣括號內(nèi)兩側(cè)的空格是不允許的。
11.trace、log信息
在 RT-Thread 中,普遍使用的 log 方式是 rt_kprintf。rt_kprintf 在 RT-Thread 被實(shí)現(xiàn)成一個(gè)采用輪詢、非中斷方式的字串輸出,能夠適合于在中斷這類"即時(shí)"顯示日志的場合。因?yàn)檫@種輪詢方式的存在,也必然會影響到日志輸出的時(shí)序關(guān)系。
建議在代碼中不要頻繁的使用 rt_kprintf 作為日志輸出,除非你真正的明白,你的代碼運(yùn)行占用的時(shí)間多一些也沒什么關(guān)系。
日志輸出應(yīng)該被設(shè)計(jì)成正常情況下是關(guān)閉狀態(tài)(例如通過一個(gè)變量或宏就能夠開啟),并且當(dāng)真正輸出日志時(shí),日志是易懂易定位問題的方式。"天書式"的日志系統(tǒng)是糟糕的,不合理的。
12.函數(shù)
在內(nèi)核編程中,函數(shù)應(yīng)該盡量精簡,僅完成相對獨(dú)立的簡單功能。函數(shù)的實(shí)現(xiàn)不應(yīng)該太長,函數(shù)實(shí)現(xiàn)太長,應(yīng)該反思能夠如何修改(或拆分)使得函數(shù)更為精簡、易懂。
13.對象
RT-Thread 內(nèi)核采用了 C 語言對象化技術(shù),命名表現(xiàn)形式是:對象名結(jié)構(gòu)體表示類定義、對象名 + 動詞短語形式表示類方法,例如:
1structrt_timer
2{
3structrt_objectparent;
4/*otherfields*/
5};
6typedefstructrt_timer*rt_timer_t;
結(jié)構(gòu)體定義 rt_timer 代表了 timer 對象的類定義;
1rt_timer_trt_timer_create(constchar*name,
2void(*timeout)(void*parameter),
3void*parameter,
4rt_tick_ttime,rt_uint8_tflag);
5rt_err_trt_timer_delete(rt_timer_ttimer);
6rt_err_trt_timer_start(rt_timer_ttimer);
7rt_err_trt_timer_stop(rt_timer_ttimer);
rt_timer + 動詞短語的形式表示能夠應(yīng)用于 timer 對象的方法。
在創(chuàng)建一個(gè)新的對象時(shí),應(yīng)該思考好,對象的內(nèi)存操作處理:是否允許一個(gè)靜態(tài)對象存在,或僅僅支持從堆中動態(tài)分配的對象。
14.格式化代碼
格式化代碼是指通過腳本自動整理你的代碼,并使其符合 RT-Thread 的編碼規(guī)范。本文提供以下兩種自動格式化代碼方法,可以自行選擇或配合使用。
使用 astyle 格式化
用 astyle 自動格式化代碼,參數(shù)如下:
1--style=allman
2--indent=spaces=4
3--indent-preproc-block
4--pad-oper
5--pad-header
6--unpad-paren
7--suffix=none
8--align-pointer=name
9--lineend=linux
10--convert-tabs
11--verbose
能滿足函數(shù)空格、縮進(jìn)、函數(shù)語句等的規(guī)范。
使用 formatting 格式化
使用 formatting 掃描文件來格式化代碼:formatting 可以滿足編碼規(guī)則的基本要求,如:
-
將源文件編碼統(tǒng)一為 UTF-8
-
將 TAB 鍵替換為 4 空格
-
將每行末尾多余的空格刪除,并統(tǒng)一換行符為 ‘ ’
審核編輯 :李倩
-
開源軟件
+關(guān)注
關(guān)注
0文章
215瀏覽量
16591 -
C語言
+關(guān)注
關(guān)注
183文章
7643瀏覽量
145467 -
編碼
+關(guān)注
關(guān)注
6文章
1037瀏覽量
56919 -
函數(shù)
+關(guān)注
關(guān)注
3文章
4416瀏覽量
67440 -
RT-Thread
+關(guān)注
關(guān)注
32文章
1606瀏覽量
44727
原文標(biāo)題:RT-Thread 編程風(fēng)格
文章出處:【微信號:strongerHuang,微信公眾號:strongerHuang】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
RT-Thread的C語言編碼規(guī)范
RT-Thread編程指南
RT-Thread用戶手冊
RT-Thread全球技術(shù)大會:螢石研發(fā)團(tuán)隊(duì)使用RT-Thread的技術(shù)挑戰(zhàn)
RT-Thread全球技術(shù)大會:Kconfig在RT-Thread中的工作機(jī)制
RT-Thread學(xué)習(xí)筆記 RT-Thread的架構(gòu)概述
RT-Thread 編程風(fēng)格
RT-Thread文檔_RT-Thread 潘多拉 STM32L475 上手指南
基于RT-Thread Studio學(xué)習(xí)
RT-Thread v5.0.2 發(fā)布
RT-Thread的編碼規(guī)范
評論