摘要:所謂無規(guī)矩不成方圓。任何團(tuán)隊(duì),規(guī)范都是怎么也繞不開的話題。特別是在我們搞嵌入式C開發(fā)的,代碼規(guī)范乃是開發(fā)的重中之重。有太多的理由去做規(guī)范,因?yàn)槊總€人的代碼編寫喜好不同,代碼風(fēng)格也迥然不同。每一個程序員心目中對好代碼都有自己的主見,統(tǒng)一的編碼規(guī)范可以像秦始皇統(tǒng)一戰(zhàn)國一樣,避免不必要的論戰(zhàn)和爭議。
有時(shí)候會幫同學(xué)看一下代碼,發(fā)現(xiàn)大多寫代碼都是隨心所欲。看起開非常頭大,雖然C語言很重要,但是C語言代碼規(guī)范也非常重要。今天分享的就是安富萊C語言編碼規(guī)范,建議初學(xué)者去官網(wǎng)看看他們的代碼,非常標(biāo)準(zhǔn)!
一、文件與目錄
1、文件及目錄的命名規(guī)定可用的字符集是A-Z;a-z;0-9;._-
。
2、源文件名后綴用小寫字母.c
和.h
。
3、文件的命名要準(zhǔn)確清晰地表達(dá)其內(nèi)容,同時(shí)文件名應(yīng)該精練,防止文件名過長而造成使用不便。在文件名中可以適當(dāng)?shù)厥褂每s寫。
以下提供兩種命名方式以供參考:(1)各程序模塊的文件命名開頭 2 個小寫字母代表本模塊的功能:如:主控程序?yàn)?code style="margin:0px 2px;padding:2px 4px;max-width:100%;font-size:14px;background-color:rgba(27,31,35,.05);font-family:'Operator Mono', Consolas, Monaco, Menlo, monospace;color:rgb(255,93,108);">mpMain.c,mpDisp.c
… (2)不寫模塊功能標(biāo)識:如:主控程序?yàn)?code style="margin:0px 2px;padding:2px 4px;max-width:100%;font-size:14px;background-color:rgba(27,31,35,.05);font-family:'Operator Mono', Consolas, Monaco, Menlo, monospace;color:rgb(255,93,108);">Main.c,Disp.c
…
4、一個軟件包或一個邏輯組件的所有頭文件和源文件建議放在一個單獨(dú)的目錄下,這樣有利于查找并使用相關(guān)的文件,有利于簡化一些編譯工具的設(shè)置。
5、對于整個項(xiàng)目需要的公共頭文件,應(yīng)存放在一個單獨(dú)的目錄下(例如:myProject/include)下,可避免其他編寫人引用時(shí)目錄太過分散的問題。
6、對于源碼文件中的段落安排,我們建議按如下的順序排列:
- a. 文件頭注釋
- b. 防止重復(fù)引用頭文件的設(shè)置
- c. #include 部分
- d. #define 部分
- e. enum 常量聲明
- f. 類型聲明和定義,包括 struct、union、typedef 等
- g. 全局變量聲明
- h. 文件級變量聲明
- i. 全局或文件級函數(shù)聲明
- j. 函數(shù)實(shí)現(xiàn)。按函數(shù)聲明的順序排列
- k. 文件尾注釋
7、在引用頭文件時(shí),不要使用絕對路徑。如果使用絕對路徑,當(dāng)需要移動目錄時(shí),必須修改所有相關(guān)代碼,繁瑣且不安全;使用相對路徑,當(dāng)需要移動目錄時(shí),只需修改編譯器的某個選項(xiàng)即可。
#include“/project/inc/hello.h”/*不應(yīng)使用絕對路徑*/
#include“../inc/hello.h”/*可以使用相對路徑*/
8、在引用頭文件時(shí),使用 <> 來引用預(yù)定義或者特定目錄的頭文件,使用 “” 來引用當(dāng)前目錄或者路徑相對于當(dāng)前目錄的頭文件。
#include/*標(biāo)準(zhǔn)頭文件*/
#include/*工程指定目錄頭文件*/
#include“global.h”/*當(dāng)前目錄頭文件*/
#include“inc/config.h”/*路徑相對于當(dāng)前目錄的頭文件*/
9、為了防止頭文件被重復(fù)引用,應(yīng)當(dāng)用ifndef/define/endif
結(jié)構(gòu)產(chǎn)生預(yù)處理塊。
#ifndef__DISP_H/*文件名前名加兩個下劃線“__”,后面加“_H”
#define__DISP_H
...
...
#endif
10、頭文件中只存放“聲明”而不存放“定義”,通過這種方式可以避免重復(fù)定義。
/*模塊 1 頭文件:module1.h */
externinta=5;/*在模塊1的.h文件中聲明變量*/
/*模塊 1 實(shí)現(xiàn)文件:module1.c */
uint8_tg_ucPara;/*在模塊1的.h文件中定義全局變量g_ucPara*/
11、如果其它模塊需要引用全局變量g_ucPara
, 只需要在文件開頭包含module1.h
/*模塊 2 實(shí)現(xiàn)文件:module2.c */
#include“module1.h”/*在模塊2中包含模塊1的.h文件*/
......
g_ucPara=0;
......
12、對于文件的長度沒有非常嚴(yán)格的要求,但應(yīng)盡量避免文件過長。一般來說,文件長度應(yīng)盡量保持在1000行之內(nèi)。
二、排版
1、程序塊要采用縮進(jìn)風(fēng)格編寫,縮進(jìn)的空格數(shù)為 4 個。
2、相對獨(dú)立的程序塊之間、變量說明之后必須加空行。
voidDemoFunc(void)
{
uint8_ti;
<----?局部變量和語句間空一行
/*功能塊1*/
for(i=0;i10;i++)
{
...
}
<----?不同的功能塊間空一行
/*功能塊2*/
for(i=0;i20;i++)
{
...
}
}
3、作符處劃分新行,操作符放在新行之首,劃分出的新行要進(jìn)行適當(dāng)?shù)目s進(jìn),使排版整齊,語句可讀。
if((ucParam1==0)&&(ucParam2==0)&&(ucParam3==0)
||(ucParam4==0))<----?長表達(dá)式需要換行書寫
{
......
}
4、不允許把多個短語句寫在一行中,即一行只寫一條語句。
rect.length=0;rect.width=0;<----?不正確的寫法
rect.length?=?0;<----?正確的寫法
rect.width?=?0;
5、對齊使用TAB 鍵,1 個 TAB 對應(yīng) 4 個字符位。
6、函數(shù)或過程的開始、結(jié)構(gòu)的定義及循環(huán)、判斷等語句中的代碼都要采用縮進(jìn)風(fēng)格,case 語句下的情況處理語句也要遵從語句縮進(jìn)要求。
7、程序塊的分界符(如大括號‘{’和‘}’ )應(yīng)各獨(dú)占一行并且位于同一列,同時(shí)與引用它們的語句左對齊。在函數(shù)體的開始、類的定義、結(jié)構(gòu)的定義、枚舉的定義以及 if、for、do、while、switch、case 語句中的程序都要采用如上的縮進(jìn)方式。對于與規(guī)則不一致的現(xiàn)存代碼,應(yīng)優(yōu)先保證同一模塊中的風(fēng)格一致性。
for(...){<----?不規(guī)范的寫法
...?/*programcode*/
}
for(...)
{<----?規(guī)范的寫法
...?/*programcode*/
}
if(...)
{<----?不規(guī)范的寫法
...?/*programcode*/
}
if(...)
{<----?規(guī)范的寫法
...?/*programcode*/
}
8、在兩個以上的關(guān)鍵字、變量、常量進(jìn)行對等操作時(shí),它們之間的操作符之前、之后或者前后要加空格;進(jìn)行非對等操作時(shí),如果是關(guān)系密切的立即操作符(如->),后不應(yīng)加空格。說明:采用這種松散方式編寫代碼的目的是使代碼更加清晰。
由于留空格所產(chǎn)生的清晰性是相對的,所以,在已經(jīng)非常清晰的語句中沒有必要再留空格,如果語句已足夠清晰則括號內(nèi)側(cè)(即左括號后面和右括號前面)不需要加空格,多重括號間不必加空格,因?yàn)樵?C語言中括號已經(jīng)是最清晰的標(biāo)志了。
在長語句中,如果需要加的空格非常多,那么應(yīng)該保持整體清晰,而在局部不加空格。給操作符留空格時(shí)不要連續(xù)留兩個以上空格。
(1)逗號、分號只在后面加空格。
int_32a,b,c;
(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;/*"->"指針前后不加空格*/
(5)if、for、while、switch 等與后面的括號間應(yīng)加空格,使 if 等關(guān)鍵字更為突出、明顯,函數(shù)名與其后的括號之間不加空格,以與保留字區(qū)別開。
if(a>=b&&c>d)
三、注釋
1、一般情況下,源程序有效注釋量必須在 20%以上。說明:注釋的原則是有助于對程序的閱讀理解,在該加的地方都加,注釋不宜太多也不能太少,注釋語言必須準(zhǔn)確、易懂、簡潔。
2、在文件的開始部分,應(yīng)該給出關(guān)于文件版權(quán)、內(nèi)容簡介、修改歷史等項(xiàng)目的說明。具體的格式請參見如下的說明。在創(chuàng)建代碼和每次更新代碼時(shí),都必須在文件的歷史記錄中標(biāo)注版本號、日期、作者、更改說明等項(xiàng)目。其中的版本號的格式為兩個數(shù)字字符和一個英文字母字符。數(shù)字字符表示大的改變,英文字符表示小的修改。如果有必要,還應(yīng)該對其它的注釋內(nèi)容也進(jìn)行同步的更改。注意:注釋第一行星號要求為 76 個,結(jié)尾行星號為 1 個。
/****************************************************************************
*Copyright(C),2010-2011,武漢xxx系統(tǒng)有限責(zé)任公司
*文件名:main.c
*內(nèi)容簡述:
*
*文件歷史:
*版本號日期作者說明
*01a2020-07-29xxx創(chuàng)建該文件
*01b2020-08-20xxx改為可以在字符串中發(fā)送回車符
*02a2020-12-03xxx增加文件頭注釋
*/
3、對于函數(shù),在函數(shù)實(shí)現(xiàn)之前,應(yīng)該給出和函數(shù)的實(shí)現(xiàn)相關(guān)的足夠而精練的注釋信息。內(nèi)容包括本函數(shù)功能介紹,調(diào)用的變量、常量說明,形參說明,特別是全局、全程或靜態(tài)變量(慎用靜態(tài)變量),要求對其初值,調(diào)用后的預(yù)期值作詳細(xì)的闡述。具體的書寫格式和包含的各項(xiàng)內(nèi)容請參見如下的例子。
下面這段函數(shù)的注釋比較標(biāo)準(zhǔn),當(dāng)然,并不局限于此格式,但上述信息建議要包含在內(nèi)。
/****************************************************************************
*函數(shù)名:SendToCard()
*功能:向讀卡器發(fā)命令,如果讀卡器進(jìn)入休眠,則首先喚醒它
*輸入:全局變量gaTxCard[]存放待發(fā)的數(shù)據(jù)
*全局變量gbTxCardLen存放長度
*輸出:無
*/
4、邊寫代碼邊注釋,修改代碼同時(shí)修改相應(yīng)的注釋,以保證注釋與代碼的一致性。不再有用的注釋要刪除。
5、注釋的內(nèi)容要清楚、明了,含義準(zhǔn)確,防止注釋二義性。說明:錯誤的注釋不但無益反而有害。注釋主要闡述代碼做了什么(What),或者如果有必要的話,闡述為什么要這么做(Why),注釋并不是用來闡述它究竟是如何實(shí)現(xiàn)算法(How)的。
6、避免在注釋中使用縮寫,特別是非常用縮寫。說明:在使用縮寫時(shí)或之前,應(yīng)對縮寫進(jìn)行必要的說明。
7、注釋應(yīng)與其描述的代碼靠近,對代碼的注釋應(yīng)放在其上方或右方(對單條語句的注釋)相鄰位置,不可放在下面,如放于上方則需與其上面的代碼用空行隔開。
例 1:不規(guī)范的寫法
/*獲取復(fù)本子系統(tǒng)索引和網(wǎng)絡(luò)指示器*/
<----?不規(guī)范的寫法,此處不應(yīng)該空行
repssn_ind?=?ssn_data[index].repssn_index;
repssn_ni?=?ssn_data[index].ni;
例 2:不規(guī)范的寫法
repssn_ind=ssn_data[index].repssn_index;
repssn_ni=ssn_data[index].ni;
/*獲取復(fù)本子系統(tǒng)索引和網(wǎng)絡(luò)指示器*/<----?不規(guī)范的寫法,應(yīng)該在語句前注釋
例 3:規(guī)范的寫法
/*獲取復(fù)本子系統(tǒng)索引和網(wǎng)絡(luò)指示器*/
repssn_ind=ssn_data[index].repssn_index;
repssn_ni=ssn_data[index].ni;
例 4:不規(guī)范的寫法,顯得代碼過于緊湊
/*codeonecomments*/
programcodeone
/*codetwocomments*/<----?不規(guī)范的寫法,兩段代碼之間需要加空行
program?code?two
例 5:規(guī)范的寫法
/*codeonecomments*/
programcodeone
/*codetwocomments*/
programcodetwo
8、注釋與所描述內(nèi)容進(jìn)行同樣的縮排。說明:可使程序排版整齊,并方便注釋的閱讀與理解。
例 1:如下例子,排版不整齊,閱讀稍感不方便。
voidexample_fun(void)
{
/*codeonecomments*/<----?不規(guī)范的寫法,注釋和代碼應(yīng)該相同的縮進(jìn)
CodeBlock?One
/*codetwocomments*/<----?不規(guī)范的寫法,注釋和代碼應(yīng)該相同的縮進(jìn)
CodeBlock?Two
}
例 2:正確的布局。
voidexample_fun(void)
{
/*codeonecomments*/
CodeBlockOne
/*codetwocomments*/
CodeBlockTwo
}
9、對變量的定義和分支語句(條件分支、循環(huán)語句等)必須編寫注釋。說明:這些語句往往是程序?qū)崿F(xiàn)某一特定功能的關(guān)鍵,對于維護(hù)人員來說,良好的注釋幫助更好的理解程序,有時(shí)甚至優(yōu)于看設(shè)計(jì)文檔。
10、對于switch語句下的case語句,如果因?yàn)樘厥馇闆r需要處理完一個case后進(jìn)入下一個case 處理,必須在該case語句處理完、下一個case語句前加上明確的注釋。說明:這樣比較清楚程序編寫者的意圖,有效防止無故遺漏 break 語句。
11、注釋格式盡量統(tǒng)一,建議使用“/* …… */”,因?yàn)?C++注釋“//”并不被所有 C 編譯器支持。
12、注釋應(yīng)考慮程序易讀及外觀排版的因素,使用的語言若是中、英兼有的,建議多使用中文,除非能非常流利準(zhǔn)確的用英文表達(dá)。說明:注釋語言不統(tǒng)一,影響程序易讀性和外觀排版,出于對維護(hù)人員的考慮,建議使用中文。
13、標(biāo)識符的命名要清晰、明了,有明確含義,同時(shí)使用完整的單詞或大家基本可以理解的縮寫,避免使人產(chǎn)生誤解。
說明:較短的單詞可通過去掉“元音”形成縮寫;較長的單詞可取單詞的頭幾個字母形成縮寫;一些單詞有大家公認(rèn)的縮寫。示例:如下單詞的縮寫能夠被大家基本認(rèn)可。
temp可縮寫為tmp;
flag可縮寫為flg;
statistic可縮寫為stat;
increment可縮寫為inc;
message可縮寫為msg;
14、命名中若使用特殊約定或縮寫,則要有注釋說明。說明:應(yīng)該在源文件的開始之處,對文件中所使用的縮寫或約定,特別是特殊的縮寫,進(jìn)行必要的注釋說明。
15、自己特有的命名風(fēng)格,要自始至終保持一致,不可來回變化。說明:個人的命名風(fēng)格,在符合所在項(xiàng)目組或產(chǎn)品組的命名規(guī)則的前提下,才可使用。(即命名規(guī)則中沒有規(guī)定到的地方才可有個人命名風(fēng)格)。
16、對于變量命名,禁止取單個字符(如 i、j、k...),建議除了要有具體含義外,還能表明其變量類型、數(shù)據(jù)類型等,但 i、j、k 作局部循環(huán)變量是允許的。說明:變量,尤其是局部變量,如果用單個字符表示,很容易敲錯(如i寫成j),而編譯時(shí)又檢查不出來,有可能為了這個小小的錯誤而花費(fèi)大量的查錯時(shí)間。
17、命名規(guī)范必須與所使用的系統(tǒng)風(fēng)格保持一致,并在同一項(xiàng)目中統(tǒng)一,比如采用 UNIX 的全小寫加下劃線的風(fēng)格或大小寫混排的方式,不要使用大小寫與下劃線混排的方式,用作特殊標(biāo)識如標(biāo)識成員變量或全局變量的 m_和 g_,其后加上大小寫混排的方式是允許的。
示例:Add_User
不允許,add_user
、AddUser
、m_AddUser
允許。
18、 除非必要,不要用數(shù)字或較奇怪的字符來定義標(biāo)識符。示例:如下命名,使人產(chǎn)生疑惑。
uint8_tdat01;
voidSet00(uint_8c);
應(yīng)改為有意義的單詞命名。
uint8_tucWidth;
voidSetParam(uint_8_ucValue);
19、在同一軟件產(chǎn)品內(nèi),應(yīng)規(guī)劃好接口部分標(biāo)識符(變量、結(jié)構(gòu)、函數(shù)及常量)的命名,防止編譯、鏈接時(shí)產(chǎn)生沖突。說明:對接口部分的標(biāo)識符應(yīng)該有更嚴(yán)格限制,防止沖突。如可規(guī)定接口部分的變量與常量之前加上“模塊”標(biāo)識等。
20、除了編譯開關(guān)/頭文件等特殊應(yīng)用,應(yīng)避免使用_EXAMPLE_TEST_
之類以下劃線開始和結(jié)尾的定義。
四、變量、結(jié)構(gòu)、常量、宏
1、為了方便書寫及記憶,變量類型采用如下重定義:
typedefunsignedcharuint8_t;
typedefunsignedshortuint16_t;
typedefunsignedlongintuint32_t;
typedefsignedcharint8_t;
typedefsignedshortint16_t;
typedefsignedlongintint32_t;
#define__IOvolatile
2、常見類型的前綴
(1)對于一些常見類型的變量,應(yīng)在其名字前標(biāo)注表示其類型的前綴。前綴用小寫字母表示。前綴的使用請參照下列表格中說明。(2)對于幾種變量類型組合,前綴可以迭加。
3、變量作用域的前綴
為了清晰的標(biāo)識變量的作用域,減少發(fā)生命名沖突,應(yīng)該在變量類型前綴之前再加上表示變量作用域的前綴,并在變量類型前綴和變量作用域前綴之間用下劃線-
隔開。
(1)對于全局變量(global variable),在其名稱前加g
和變量類型符號前綴。
uint32_tg_ulParaWord;
uint8_tg_ucByte;
(2)對于靜態(tài)變量(static variable),在其名稱前加“s”和變量類型符號前綴。
staticuint32_ts_ulParaWord;
staticuint8_ts_ucByte;
(3)函數(shù)內(nèi)部等局部變量前不加作用域前綴。(4)對于常量,當(dāng)可能發(fā)生作用域和名字沖突問題時(shí),以上幾條規(guī)則對于常量同樣適用。注意,雖然常量名的核心部分全部大寫,但此時(shí)常量的前綴仍然用小寫字母,以保持前綴的一致性。
4、對于結(jié)構(gòu)體命名類型,表示類型的名字,所有名字以小寫字母tag
開頭,之后每個英文單詞的第一個字母大寫(包括第一個單詞的第一個字母),其他字母小寫,結(jié)尾_T
標(biāo)識。單詞之間不使用下劃線分隔,結(jié)構(gòu)體變量以t
開頭。
/*結(jié)構(gòu)體命名類型名*/
typedefstructtagBillQuery_T
{
...
}BillQuery_T;
/*結(jié)構(gòu)體變量定義*/
BillQuery_TtBillQuery;
對于枚舉定義全部采用大寫,結(jié)尾_E標(biāo)識。
typedefenum
{
KB_F1=0,/*F1鍵代碼*/
KB_F2,/*F2鍵代碼*/
KB_F3/*F3鍵代碼*/
}KEY_CODE_E;
5、常量、宏、模版的名字應(yīng)該全部大寫。如果這些名字由多個單詞組成,則單詞之間用下劃線分隔。宏指所有用宏形式定義的名字,包括常量類和函數(shù)類;常量也包括枚舉中的常量成員。
#defineLOG_BUF_SIZE8000
6、不推薦使用位域。
五、函數(shù)
1、函數(shù)的命名規(guī)則。每一個函數(shù)名前綴需包含模塊名,模塊名為小寫,與函數(shù)名區(qū)別開。如:uartReceive(串口接收)備注:對于非常簡單的程序,可以不加模塊名。
2、函數(shù)的的形參需另啟一行,在后面給予說明,形參都以下劃線_開頭,已示與普通變量進(jìn)行區(qū)分,對于沒有形參為空的函數(shù)(void)括號緊跟函數(shù)后面。
/******************************************************************************
*函數(shù)名:uartConvUartBaud
*功能:波特率轉(zhuǎn)換
*輸入:_ulBaud :波特率
*輸出:無
*返回:uint32-轉(zhuǎn)換后的波特率值
*/
uint32_tuartConvUartBaud(uint32_t_ulBaud)
{
uint32_tulBaud;
ulBaud=ulBaud*2;/*計(jì)算波特率*/
......
returnulBaud;
}
復(fù)制代碼
3、一個函數(shù)僅完成一件功能。
4、函數(shù)名應(yīng)準(zhǔn)確描述函數(shù)的功能。避免使用無意義或含義不清的動詞為函數(shù)命名。使用動賓詞組為執(zhí)行某操作的函數(shù)命名。說明:避免用含義不清的動詞如process、handle等為函數(shù)命名,因?yàn)檫@些動詞并沒有說明要具體做什么。示例:參照如下方式命名函數(shù)。
voidPrintRecord(uint32_t_RecInd);
int32InputRecord(void);
uint8_tGetCurrentColor(void);
5、檢查函數(shù)所有參數(shù)輸入的有效性。說明:如果約定由調(diào)用方檢查參數(shù)輸入,則應(yīng)使用assert()之類的宏,來驗(yàn)證所有參數(shù)輸入的有效性。
6、檢查函數(shù)所有非參數(shù)輸入的有效性,如數(shù)據(jù)文件、公共變量等。說明:函數(shù)的輸入主要有兩種:一種是參數(shù)輸入;另一種是全局變量、數(shù)據(jù)文件的輸入,即非參數(shù)輸入。函數(shù)在使用輸入之前,應(yīng)進(jìn)行必要的檢查。
7、防止將函數(shù)的參數(shù)作為工作變量。說明:將函數(shù)的參數(shù)作為工作變量,有可能錯誤地改變參數(shù)內(nèi)容,所以很危險(xiǎn)。對必須改變的參數(shù),最好先用局部變量代之,最后再將該局部變量的內(nèi)容賦給該參數(shù)。
8、避免設(shè)計(jì)五個以上參數(shù)函數(shù),不使用的參數(shù)從接口中去掉。說明:目的減少函數(shù)間接口的復(fù)雜度,復(fù)雜的參數(shù)可以使用結(jié)構(gòu)傳遞。
9、在調(diào)用函數(shù)填寫參數(shù)時(shí),應(yīng)盡量減少沒有必要的默認(rèn)數(shù)據(jù)類型轉(zhuǎn)換或強(qiáng)制數(shù)據(jù)類型轉(zhuǎn)換。說明:因?yàn)閿?shù)據(jù)類型轉(zhuǎn)換或多或少存在危險(xiǎn)。
10、避免使用 BOOL 參數(shù)。說明:原因有二,其一是BOOL參數(shù)值無意義,TURE/FALSE的含義是非常模糊的,在調(diào)用時(shí)很難知道該參數(shù)到底傳達(dá)的是什么意思;其二是BOOL參數(shù)值不利于擴(kuò)充。還有NULL也是一個無意義的單詞。
11、函數(shù)的返回值要清楚、明了。除非必要,最好不要把與函數(shù)返回值類型不同的變量,以編譯系統(tǒng)默認(rèn)的轉(zhuǎn)換方式或強(qiáng)制的轉(zhuǎn)換方式作為返回值返回。
12、防止把沒有關(guān)聯(lián)的語句放到一個函數(shù)中。說明:防止函數(shù)或過程內(nèi)出現(xiàn)隨機(jī)內(nèi)聚。隨機(jī)內(nèi)聚是指將沒有關(guān)聯(lián)或關(guān)聯(lián)很弱的語句放到同一個函數(shù)或過程中。隨機(jī)內(nèi)聚給函數(shù)或過程的維護(hù)、測試及以后的升級等造成了不便,同時(shí)也使函數(shù)或過程的功能不明確。使用隨機(jī)內(nèi)聚函數(shù),常常容易出現(xiàn)在一種應(yīng)用場合需要改進(jìn)此函數(shù),而另一種應(yīng)用場合又不允許這種改進(jìn),從而陷入困境。
在編程時(shí),經(jīng)常遇到在不同函數(shù)中使用相同的代碼,許多開發(fā)人員都愿把這些代碼提出來,并構(gòu)成一個新函數(shù)。若這些代碼關(guān)聯(lián)較大并且是完成一個功能的,那么這種構(gòu)造是合理的,否則這種構(gòu)造將產(chǎn)生隨機(jī)內(nèi)聚的函數(shù)。示例:如下函數(shù)就是一種隨機(jī)內(nèi)聚。
voidInitVar(void)
{
Rect.length=0;
Rect.width=0;/*初始化矩形的長與寬*/
Point.x=10;
Point.y=10;/*初始化“點(diǎn)”的坐標(biāo)*/
}
矩形的長、寬與點(diǎn)的坐標(biāo)基本沒有任何關(guān)系,故以上函數(shù)是隨機(jī)內(nèi)聚。應(yīng)如下分為兩個函數(shù):
voidInitRect(void)
{
Rect.length=0;
Rect.width=0;/*初始化矩形的長與寬*/
}
voidInitPoint(void)
{
Point.x=10;
Point.y=10;/*初始化“點(diǎn)”的坐標(biāo)*/
}
13、減少函數(shù)本身或函數(shù)間的遞歸調(diào)用。
說明:遞歸調(diào)用特別是函數(shù)間的遞歸調(diào)用(如A->B->C->A),影響程序的可理解性;遞歸調(diào)用一般都占用較多的系統(tǒng)資源(如棧空間);遞歸調(diào)用對程序的測試有一定影響。故除非為某些算法或功能的實(shí)現(xiàn)方便,應(yīng)減少沒必要的遞歸調(diào)用。
14、改進(jìn)模塊中函數(shù)的結(jié)構(gòu),降低函數(shù)間的耦合度,并提高函數(shù)的獨(dú)立性以及代碼可讀性、效率和可維護(hù)性。優(yōu)化函數(shù)結(jié)構(gòu)時(shí),要遵守以下原則:
- 能影響模塊功能的實(shí)現(xiàn)。
- 仔細(xì)考查模塊或函數(shù)出錯處理及模塊的性能要求并進(jìn)行完善。
- 通過分解或合并函數(shù)來改進(jìn)軟件結(jié)構(gòu)。
- 考查函數(shù)的規(guī)模,過大的要進(jìn)行分解。
- 降低函數(shù)間接口的復(fù)雜度。
- 不同層次的函數(shù)調(diào)用要有較合理的扇入、扇出。
- 函數(shù)功能應(yīng)可預(yù)測。
- 提高函數(shù)內(nèi)聚。(單一功能的函數(shù)內(nèi)聚最高)
說明:對初步劃分后的函數(shù)結(jié)構(gòu)應(yīng)進(jìn)行改進(jìn)、優(yōu)化,使之更為合理。
審核編輯 :李倩
-
C語言
+關(guān)注
關(guān)注
180文章
7630瀏覽量
140450 -
代碼
+關(guān)注
關(guān)注
30文章
4887瀏覽量
70266
原文標(biāo)題:寫碼如寫詩!嵌入式C代碼規(guī)范有多重要?
文章出處:【微信號:mcu168,微信公眾號:硬件攻城獅】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
安富利榮獲Bourns三項(xiàng)大獎
安富利亮相第十八屆中國電子信息年會

安富利榮獲商飛時(shí)代“開發(fā)貢獻(xiàn)獎”
安富利中國區(qū)總裁董花:安富利眼中的2025新征程

安富利中國2024年獲多項(xiàng)人力資源管理大獎
安富利榮獲安森美“2024年度智能感知參考設(shè)計(jì)創(chuàng)新獎”
安富利榮獲TE 2024年度最佳分銷商獎
安富利榮獲2024年度金旗獎企業(yè)社會責(zé)任金獎
ADS1281 PCM編碼規(guī)范應(yīng)該在哪里找?
安富利榮獲Nordic年度最佳分銷商獎
C語言與Java語言的對比
安富利與合作伙伴共筑綠色未來

安富利推出新品牌Tria?以整合嵌入式計(jì)算選項(xiàng)
C語言編碼規(guī)范,這才是最理想的!

評論