1最重要的規(guī)則
編寫代碼時最重要的一條規(guī)則是:檢查周圍的代碼并嘗試模仿它。
作為維護人員,如果收到的補丁明顯與周圍代碼的編碼風格不同,這是令人沮喪的。這是不尊重人的,就像某人穿著泥濘的鞋子走進一間一塵不染的房子。
因此,無論本文推薦的是什么,如果已經編寫了代碼并且您正在對其進行修補,請保持其當前的樣式一致,即使它不是您最喜歡的樣式。
2一般性的規(guī)則
這里列出了最明顯和最重要的一般規(guī)則。在你繼續(xù)閱讀其他章節(jié)之前,請仔細檢查它們。
使用C99標準
不使用制表符,而是使用空格
每個縮進級別使用4個空格
在關鍵字和左括號之間使用一個空格
在函數名和左括號之間不要使用空格
int32_ta=sum(4,3);/*OK*/ int32_ta=sum(4,3);/*Wrong*/
不要在變量/函數/宏/類型中使用_或前綴。這是為C語言本身保留的
對于嚴格的模塊私有函數,使用prv_name前綴
對于包含下劃線_char的變量/函數/宏/類型,只能使用小寫字母
左花括號總是與關鍵字(for,while,do,switch,if,…)在同一行
size_ti; for(i=0;i5;?++i)?{???????????/*?OK?*/ } for?(i?=?0;?i?5;?++i){????????????/*?Wrong?*/ } for?(i?=?0;?i?5;?++i)?????????????/*?Wrong?*/ { }
在比較操作符和賦值操作符之前和之后使用單個空格
int32_ta; a=3+4;/*OK*/ for(a=0;a5;?++a)?/*?OK?*/ a=3+4;??????????????????/*?Wrong?*/ a?=?3+4;????????????????/*?Wrong?*/ for?(a=0;a<5;++a)???????/*?Wrong?*/
每個逗號后用單空格
func_name(5,4);/*OK*/ func_name(4,3);/*Wrong*/
不要初始化靜態(tài)和全局變量為0(或NULL),讓編譯器為您做
staticint32_ta;/*OK*/ staticint32_tb=4;/*OK*/ staticint32_ta=0;/*Wrong*/ voidmy_func(void){ staticint32_t*ptr;/*OK*/ staticcharabc=0;/*Wrong*/ }
在同一行中聲明所有相同類型的局部變量
voidmy_func(void){ chara;/*OK*/ charb;/*Wrong,variablewithchartypealreadyexists*/ chara,b;/*OK*/ }
按順序聲明局部變量
i. 自定義結構和枚舉
ii. 整數類型,更寬的無符號類型優(yōu)先
iii. 單/雙浮點
intmy_func(void){ /*1*/ my_struct_tmy;/*Firstcustomstructures*/ my_struct_ptr_t*p;/*Pointerstoo*/ /*2*/ uint32_ta; int32_tb; uint16_tc; int16_tg; charh; /*...*/ /*3*/ doubled; floatf; }
總是在塊的開頭聲明局部變量,在第一個可執(zhí)行語句之前
在for循環(huán)中聲明計數器變量
/*OK*/ for(size_ti=0;i10;?++i) /*?OK,?if?you?need?counter?variable?later?*/ size_t?i; for?(i?=?0;?i?10;?++i)?{ ????if?(...)?{ ????????break; ????} } if?(i?*?10)?{ } /*?Wrong?*/ size_t?i; for?(i?=?0;?i?10;?++i)?...
避免在聲明中使用函數調用來賦值變量,除了單個變量
voida(void){ /*Avoidfunctioncallswhendeclaringvariable*/ int32_ta,b=sum(1,2); /*Usethis*/ int32_ta,b; b=sum(1,2); /*Thisisok*/ uint8_ta=3,b=4; }
除了char、float或double之外,始終使用stdint.h標準庫中聲明的類型。例如,8位的uint8_t等
不要使用stdbool.h庫。分別使用1或0表示真或假
/*OK*/ uint8_tstatus; status=0; /*Wrong*/ #include boolstatus=true;
永遠不要與真實相比較。例如,使用if(check_func()){…}替換if (check_func() * 1)
總是將指針與空值進行比較
void*ptr; /*...*/ /*OK,compareagainstNULL*/ if(ptr*NULL||ptr!=NULL){ } /*Wrong*/ if(ptr||!ptr){ }
總是使用前增量(和遞減),而不是后增量(和遞減)
int32_ta=0; ... a++;/*Wrong*/ ++a;/*OK*/ for(size_tj=0;j10;?++j)?{}??/*?OK?*/
總是使用size_t作為長度或大小變量
如果函數不應該修改指針所指向的內存,則總是使用const作為指針
如果不應該修改函數的形參或變量,則總是使用const
/*Whendcouldbemodified,datapointedtobydcouldnotbemodified*/ void my_func(constvoid*d){ } /*Whendanddatapointedtobydbothcouldnotbemodified*/ void my_func(constvoid*constd){ } /*Notrequired,itisadvised*/ void my_func(constsize_tlen){ } /*Whendshouldnotbemodifiedinsidefunction,onlydatapointedtobydcouldbemodified*/ void my_func(void*constd){ }
當函數可以接受任何類型的指針時,總是使用void*,不要使用uint8_t*。函數在實現時必須注意正確的類型轉換
/* *Tosenddata,functionshouldnotmodifymemorypointedtoby`data`variable *thus`const`keywordisimportant * *Tosendgenericdata(ortowritethemtofile) *anytypemaybepassedfordata, *thususe`void*` */ /*OKexample*/ voidsend_data(constvoid*data,size_tlen){/*OK*/ /*Donotcast`void*`or`constvoid*`*/ constuint8_t*d=data;/*Functionhandlespropertypeforinternalusage*/ } voidsend_data(constvoid*data,intlen){/*Wrong,notnotuseint*/ }
總是使用括號和sizeof操作符
不要使用變長數組。使用動態(tài)內存分配代替標準Cmalloc和自由函數,或者如果庫/項目提供了自定義內存分配,使用它的實現看看LwMEM,一個自定義內存管理庫。
/*OK*/ #include void my_func(size_tsize){ int32_t*arr; arr=malloc(sizeof(*arr)*n);/*OK,Allocatememory*/ arr=malloc(sizeof*arr*n);/*Wrong,bracketsforsizeofoperatoraremissing*/ if(arr*NULL){ /*FAIL,nomemory*/ } free(arr);/*Freememoryafterusage*/ } /*Wrong*/ void my_func(size_tsize){ int32_tarr[size];/*Wrong,donotuseVLA*/ }
總是將variable與0進行比較,除非它被視為布爾類型
永遠不要將布爾處理的變量與0或1進行比較。用NOT(!)代替
size_tlength=5;/*Countervariable*/ uint8_tis_ok=0;/*Boolean-treatedvariable*/ if(length)/*Wrong,lengthisnottreatedasboolean*/ if(length>0)/*OK,lengthistreatedascountervariablecontainingmultivalues,notonly0or1*/ if(length*0)/*OK,lengthistreatedascountervariablecontainingmultivalues,notonly0or1*/ if(is_ok)/*OK,variableistreatedasboolean*/ if(!is_ok)/*OK,-||-*/ if(is_ok*1)/*Wrong,nevercomparebooleanvariableagainst1!*/ if(is_ok*0)/*Wrong,use!fornegativecheck*/
對于注釋,總是使用/*comment */,即使是單行注釋
在頭文件中總是包含帶有extern關鍵字的c++檢查
每個函數都必須包含doxygen-enabled注釋,即使函數是靜態(tài)的
使用英文名稱/文本的函數,變量,注釋
變量使用小寫字母
如果變量包含多個名稱,請使用下劃線。force_redraw。不要使用forceRedraw
對于C標準庫的包含文件,請始終使用<和>。例如,#include
對于自定義庫,請始終使用""。例如,#include“my_library.h”
當轉換為指針類型時,總是將星號與類型對齊,例如。uint8_t* t = (uint8_t*)var_width_diff_type
始終尊重項目或庫中已經使用的代碼風格
3注釋相關的規(guī)則
不允許以//開頭的注釋??偸鞘褂芒?comment */,即使是單行注釋
對于多行注釋,每行使用空格+星號
/* *Thisismulti-linecomments, *writtenin2lines(ok) */ /** *Wrong,usedouble-asteriskonlyfordoxygendocumentation */ /* *Singlelinecommentwithoutspacebeforeasterisk(wrong) */ /* *Singlelinecommentinmulti-lineconfiguration(wrong) */ /*Singlelinecomment(ok)*/
注釋時使用12個縮進(12 * 4個空格)偏移量。如果語句大于12個縮進,將注釋4-空格對齊(下面的例子)到下一個可用縮進
voidmy_func(void){ chara,b; a=call_func_returning_char_a(a);/*Thisiscommentwith12*4spacesindentfrombeginningofline*/ b=call_func_returning_char_a_but_func_name_is_very_long(a);/*Thisiscomment,alignedto4-spacesindent*/ }
04函數定義的規(guī)則
每個可以從模塊外部訪問的函數都必須包含函數原型(或聲明)
函數名必須小寫,可以用下劃線_分隔。(這個原則好像因人而異)
/*OK*/ voidmy_func(void); voidmyfunc(void); /*Wrong*/ voidMYFunc(void); voidmyFunc();
當函數返回指針時,將星號對齊到返回類型
/*OK*/ constchar*my_func(void); my_struct_t*my_func(int32_ta,int32_tb); /*Wrong*/ constchar*my_func(void); my_struct_t*my_func(void);
對齊所有的功能原型(使用相同/相似的功能)以提高可讀性
/*OK,functionnamesaligned*/ voidset(int32_ta); my_type_tget(void); my_ptr_t*get_ptr(void); /*Wrong*/ voidset(int32_ta); constchar*get(void);
函數實現必須在單獨的行中包含返回類型和可選的其他關鍵字
/*OK*/ int32_t foo(void){ return0; } /*OK*/ staticconstchar* get_string(void){ return"Helloworld! "; } /*Wrong*/ int32_tfoo(void){ return0; }
5變量相關的規(guī)則
使變量名全部小寫,下劃線_字符可選
/*OK*/ int32_ta; int32_tmy_var; int32_tmyvar; /*Wrong*/ int32_tA; int32_tmyVar; int32_tMYVar;
按類型將局部變量分組在一起
voidfoo(void){ int32_ta,b;/*OK*/ chara; charb;/*Wrong,chartypealreadyexists*/ }
不要在第一個可執(zhí)行語句之后聲明變量
voidfoo(void){ int32_ta; a=bar(); int32_tb;/*Wrong,thereisalreadyexecutablestatement*/ }
你可以在下一個縮進級別中聲明新的變量
int32_ta,b; a=foo(); if(a){ int32_tc,d;/*OK,canddareinif-statementscope*/ c=foo(); int32_te;/*Wrong,therewasalreadyexecutablestatementinsideblock*/ }
用星號聲明指針變量與類型對齊
/*OK*/ char*a; /*Wrong*/ char*a; char*a;
當聲明多個指針變量時,可以使用星號對變量名進行聲明
/*OK*/ char*p,*n;
6結構、枚舉類型定義
結構名或枚舉名必須小寫,單詞之間有下劃線_字符
結構或枚舉可以包含typedef關鍵字
所有結構成員都必須小寫
所有枚舉成員必須是大寫的
結構/枚舉必須遵循doxygen文檔語法
在聲明結構體時,它可以使用以下三種不同的選項之一:
1. 當結構體僅用名稱聲明時,它的名稱后不能包含_t后綴。
structstruct_name{ char*a; charb; };
2. 當只使用typedef聲明結構時,它的名稱后面必須包含_t后綴。
typedefstruct{ char*a; charb; }struct_name_t;
3. 當結構用name和typedef聲明時,它不能包含t作為基本名稱,它必須在它的名稱后面包含t后綴作為typedef部分。
typedefstructstruct_name{ char*a; charb; charc; }struct_name_t;
錯誤聲明的例子及其建議的糾正:
/*aandbmustbeseparatedto2lines*/ /*Nameofstructurewithtypedefmustinclude_tsuffix*/ typedefstruct{ int32_ta,b; }a; /*Correctedversion*/ typedefstruct{ int32_ta; int32_tb; }a_t; /*Wrongname,itmustnotinclude_tsuffix*/ structname_t{ int32_ta; int32_tb; }; /*Wrongparameters,mustbealluppercase*/ typedefenum{ MY_ENUM_TESTA, my_enum_testb, }my_enum_t;
在聲明時初始化結構時,使用C99初始化風格
/*OK*/ a_ta={ .a=4, .b=5, }; /*Wrong*/ a_ta={1,2};
當為函數句柄引入newtypedef時,使用_fn后綴
/*Functionaccepts2parametersandreturnsuint8_t*/ /*Nameoftypedefhas`_fn`suffix*/ typedefuint8_t(*my_func_typedef_fn)(uint8_tp1,constchar*p2);
07復合語句規(guī)則
每個復合語句必須包括左花括號和右花括號,即使它只包含1個嵌套語句
每個復合語句必須包含單個縮進;嵌套語句時,每個嵌套包含1個縮進大小
/*OK*/ if(c){ do_a(); }else{ do_b(); } /*Wrong*/ if(c) do_a(); else do_b(); /*Wrong*/ if(c)do_a(); elsedo_b();
在if或if-else-if語句的情況下,else必須與第一條語句的右括號在同一行
/*OK*/ if(a){ }elseif(b){ }else{ } /*Wrong*/ if(a){ } else{ } /*Wrong*/ if(a){ } else { }
在do-while語句的情況下,while部分必須與do部分的右括號在同一行
/*OK*/ do{ int32_ta; a=do_a(); do_b(a); }while(check()); /*Wrong*/ do { /*...*/ }while(check()); /*Wrong*/ do{ /*...*/ } while(check());
每一個開括號都需要縮進
if(a){ do_a(); }else{ do_b(); if(c){ do_c(); } }
不要做沒有花括號的復合語句,即使是單個語句。下面的例子展示了一些不好的做法
if(a)do_b(); elsedo_c(); if(a)do_a();elsedo_b();
空while循環(huán)、do-while循環(huán)或for循環(huán)必須包含花括號
/*OK*/ while(is_register_bit_set()){} /*Wrong*/ while(is_register_bit_set()); while(is_register_bit_set()){} while(is_register_bit_set()){ }
如果while(或for、do-while等)為空(嵌入式編程中也可能是這種情況),請使用空的單行括號
/*Waitforbittobesetinembeddedhardwareunit uint32_t*addr=HW_PERIPH_REGISTER_ADDR; /*Waitbit13tobeready*/ while(*addr&(1<13))?{}????????/*?OK,?empty?loop?contains?no?spaces?inside?curly?brackets?*/ while?(*addr?&?(1?<13))?{?}???????/*?Wrong?*/ while?(*addr?&?(1?<13))?{?????????/*?Wrong?*/ } while?(*addr?&?(1?<13));??????????/*?Wrong,?curly?brackets?are?missing.?Can?lead?to?compiler?warnings?or?unintentional?bugs?*/
盡量避免在循環(huán)塊內遞增變量,參見示例
/*Notrecommended*/ int32_ta=0; while(a10)?{ ????. ????.. ????... ????++a; } /*?Better?*/ for?(size_t?a?=?0;?a?10;?++a)?{ } /*?Better,?if?inc?may?not?happen?in?every?cycle?*/ for?(size_t?a?=?0;?a?10;?)?{ ????if?(...)?{ ????????++a; ????} }
8分支語句規(guī)則
為每個case語句添加單個縮進
使用額外的單縮進break語句在每個case或default
/*OK,everycasehassingleindent*/ /*OK,everybreakhasadditionalindent*/ switch(check()){ case0: do_a(); break; case1: do_b(); break; default: break; } /*Wrong,caseindentmissing*/ switch(check()){ case0: do_a(); break; case1: do_b(); break; default: break; } /*Wrong*/ switch(check()){ case0: do_a(); break;/*Wrong,breakmusthaveindentasitisundercase*/ case1: do_b();/*Wrong,indentundercaseismissing*/ break; default: break; }
總是包含default語句
/*OK*/ switch(var){ case0: do_job(); break; default:break; } /*Wrong,defaultismissing*/ switch(var){ case0: do_job(); break; }
如果需要局部變量,則使用花括號并在里面放入break語句。將左花括號放在case語句的同一行
switch(a){ /*OK*/ case0:{ int32_ta,b; charc; a=5; /*...*/ break; } /*Wrong*/ case1: { int32_ta; break; } /*Wrong,breakshallbeinside*/ case2:{ int32_ta; } break; }
9 宏和預處理指令
總是使用宏而不是文字常量,特別是對于數字
所有的宏必須是全大寫的,并帶有下劃線_字符(可選),除非它們被明確標記為function,將來可能會被常規(guī)函數語法替換
/*OK*/ #defineMY_MACRO(x)((x)*(x)) /*Wrong*/ #definesquare(x)((x)*(x))
總是用圓括號保護輸入參數
/*OK*/ #defineMIN(x,y)((x)(y)???(x)?:?(y)) /*?Wrong?*/ #define?MIN(x,?y)???????????x?
總是用括號保護最終的宏計算
/*Wrong*/ #defineMIN(x,y)(x)(y)???(x)?:?(y) #define?SUM(x,?y)???????????(x)?+?(y) /*?Imagine?result?of?this?equation?using?wrong?SUM?implementation?*/ int32_t?x?=?5?*?SUM(3,?4);??/*?Expected?result?is?5?*?7?=?35?*/ int32_t?x?=?5?*?(3)?+?(4);??/*?It?is?evaluated?to?this,?final?result?=?19?which?is?not?what?we?expect?*/ /*?Correct?implementation?*/ #define?MIN(x,?y)???????????((x)?(y)???(x)?:?(y)) #define?SUM(x,?y)???????????((x)?+?(y))
當宏使用多個語句時,使用do-while(0)語句保護它
typedefstruct{ int32_tpx,py; }point_t; point_tp;/*Definenewpoint*/ /*Wrongimplementation*/ /*Definemacrotosetpoint*/ #defineSET_POINT(p,x,y)(p)->px=(x);(p)->py=(y)/*2statements.Lastoneshouldnotimplementsemicolon*/ SET_POINT(&p,3,4);/*Setpointtoposition3,4.Thisevaluatesto...*/ (&p)->px=(3);(&p)->py=(4);/*...tothis.Inthisexamplethisisnotaproblem.*/ /*Considerthisuglycode,howeveritisvalidbyCstandard(notrecommended)*/ if(a)/*Ifaistrue*/ if(b)/*Ifbistrue*/ SET_POINT(&p,3,4);/*Setpointtox=3,y=4*/ else SET_POINT(&p,5,6);/*Setpointtox=5,y=6*/ /*Evaluatestocodebelow.Doyouseetheproblem?*/ if(a) if(b) (&p)->px=(3);(&p)->py=(4); else (&p)->px=(5);(&p)->py=(6); /*Orifwerewriteitalittle*/ if(a) if(b) (&p)->px=(3); (&p)->py=(4); else (&p)->px=(5); (&p)->py=(6); /* *Askyourselfaquestion:Towhich`if`statement`else`keywordbelongs? * *Basedonfirstpartofcode,answerisstraight-forward.Toinner`if`statementwhenwecheck`b`condition *Actualanswer:Compilationerroras`else`belongsnowhere */ /*Betterandcorrectimplementationofmacro*/ #defineSET_POINT(p,x,y)do{(p)->px=(x);(p)->py=(y);}while(0)/*2statements.Nosemicolonafterwhileloop*/ /*Orevenbetter*/ #defineSET_POINT(p,x,y)do{/*Backslashindicatesstatementcontinuesinnewline*/ (p)->px=(x); (p)->py=(y); }while(0)/*2statements.Nosemicolonafterwhileloop*/ /*Noworiginalcodeevaluatesto*/ if(a) if(b) do{(&p)->px=(3);(&p)->py=(4);}while(0); else do{(&p)->px=(5);(&p)->py=(6);}while(0); /*Everypartof`if`or`else`containsonly`1`innerstatement(do-while),hencethisisvalidevaluation*/ /*Tomakecodeperfect,usebracketsforeveryif-ifelse-elsestatements*/ if(a){/*Ifaistrue*/ if(b){/*Ifbistrue*/ SET_POINT(&p,3,4);/*Setpointtox=3,y=4*/ }else{ SET_POINT(&p,5,6);/*Setpointtox=5,y=6*/ } }
不縮進子語句內#if語句
/*OK*/ #ifdefined(XYZ) #ifdefined(ABC) /*dowhenABCdefined*/ #endif/*defined(ABC)*/ #else/*defined(XYZ)*/ /*DowhenXYZnotdefined*/ #endif/*!defined(XYZ)*/ /*Wrong*/ #ifdefined(XYZ) #ifdefined(ABC) /*dowhenABCdefined*/ #endif/*defined(ABC)*/ #else/*defined(XYZ)*/ /*DowhenXYZnotdefined*/ #endif/*!defined(XYZ)*/ 文檔
文檔化的代碼允許doxygen解析和通用的html/pdf/latex輸出,因此正確地執(zhí)行是非常重要的。
對變量、函數和結構/枚舉使用doxygen支持的文檔樣式
經常使用作為doxygen,不要使用@
始終使用5x4空格(5個制表符)作為文本行開始的偏移量
/** *riefHoldspointertofirstentryinlinkedlist *Beginningofthistextis5tabs(20spaces)frombeginningofline */ static type_t*list;
每個結構/枚舉成員都必須包含文檔
注釋的開頭使用12x4空格偏移量
/** *riefThisispointstruct * oteThisstructureisusedtocalculateallpoint *relatedstuff */ typedefstruct{ int32_tx;/*!
函數的文檔必須在函數實現中編寫(通常是源文件)
函數必須包括簡要和所有參數文檔
如果每個參數分別為in或out輸入和輸出,則必須注意
如果函數返回某個值,則必須包含返回形參。這不適用于void函數
函數可以包含其他doxygen關鍵字,如note或warning
在參數名和描述之間使用冒號:
/** *riefSum`2`numbers *param[in]a:Firstnumber *param[in]b:Secondnumber *returnSumofinputvalues */ int32_t sum(int32_ta,int32_tb){ returna+b; } /** *riefSum`2`numbersandwriteittopointer * oteThisfunctiondoesnotreturnvalue,itstoresittopointerinstead *param[in]a:Firstnumber *param[in]b:Secondnumber *param[out]result:Outputvariableusedtosaveresult */ void void_sum(int32_ta,int32_tb,int32_t*result){ *result=a+b; }
如果函數返回枚舉的成員,則使用ref關鍵字指定哪個成員
/** *riefMyenumeration */ typedefenum{ MY_ERR,/*!
對常量或數字使用符號(' NULL ' => NULL)
/** *riefGetdatafrominputarray *param[in]in:Inputdata *returnPointertooutputdataonsuccess,`NULL`otherwise */ constvoid* get_data(constvoid*in){ returnin; }
宏的文檔必須包括hideinitializer doxygen命令
/** *riefGetminimalvaluebetween`x`and`y` *param[in]x:Firstvalue *param[in]y:Secondvalue *returnMinimalvaluebetween`x`and`y` *hideinitializer */ #defineMIN(x,y)((x)(y)???(x)?:?(y))
10頭/源文件
在文件末尾留下一個空行
每個文件都必須包括文件的doxygen注釋和后跟空行的簡要描述(使用doxygen時)
/** *filetemplate.h *riefTemplateincludefile */ /*Hereisemptyline*/
每個文件(頭文件或源文件)必須包含許可證(開始注釋包括單個星號,因為doxygen必須忽略這個)
使用與項目/庫已經使用的相同的許可證
/** *filetemplate.h *riefTemplateincludefile */ /* *Copyright(c)yearFirstNameLASTNAME * *Permissionisherebygranted,freeofcharge,toanyperson *obtainingacopyofthissoftwareandassociateddocumentation *files(the"Software"),todealintheSoftwarewithoutrestriction, *includingwithoutlimitationtherightstouse,copy,modify,merge, *publish,distribute,sublicense,and/orsellcopiesoftheSoftware, *andtopermitpersonstowhomtheSoftwareisfurnishedtodoso, *subjecttothefollowingconditions: * *Theabovecopyrightnoticeandthispermissionnoticeshallbe *includedinallcopiesorsubstantialportionsoftheSoftware. * *THESOFTWAREISPROVIDED"ASIS",WITHOUTWARRANTYOFANYKIND, *EXPRESSORIMPLIED,INCLUDINGBUTNOTLIMITEDTOTHEWARRANTIES *OFMERCHANTABILITY,FITNESSFORAPARTICULARPURPOSE *ANDNONINFRINGEMENT.INNOEVENTSHALLTHEAUTHORSORCOPYRIGHT *HOLDERSBELIABLEFORANYCLAIM,DAMAGESOROTHERLIABILITY, *WHETHERINANACTIONOFCONTRACT,TORTOROTHERWISE,ARISING *FROM,OUTOFORINCONNECTIONWITHTHESOFTWAREORTHEUSEOR *OTHERDEALINGSINTHESOFTWARE. * *Thisfileispartoflibrary_name. * *Author:FirstNameLASTNAME */@example.com>
頭文件必須包含保護符#ifndef
頭文件必須包含c++檢查
在c++檢查之外包含外部頭文件
首先用STLC文件包含外部頭文件,然后是應用程序自定義文件
頭文件必須包含其他所有頭文件,以便正確編譯,但不能包含更多頭文件(如果需要,.c應該包含其余的頭文件)
頭文件必須只公開模塊公共變量/類型/函數
在頭文件中使用extern作為全局模塊變量,稍后在源文件中定義它們
/*file.h...*/ #ifndef... externint32_tmy_variable;/*Thisisglobalvariabledeclarationinheader*/ #endif /*file.c...*/ int32_tmy_variable;/*Actuallydefinedinsource*/
不要把.c文件包含在另一個.c文件中
.c文件應該首先包含相應的.h文件,然后是其他文件,除非另有明確的必要
在頭文件中不包含模塊私有聲明
頭文件示例(示例中沒有l(wèi)icense)
/*Licensecomeshere*/ #ifndefTEMPLATE_HDR_H #defineTEMPLATE_HDR_H /*Includeheaders*/ #ifdef__cplusplus extern"C"{ #endif/*__cplusplus*/ /*Filecontenthere*/ #ifdef__cplusplus } #endif/*__cplusplus*/ #endif/*TEMPLATE_HDR_H*/
責任編輯:lq6
-
嵌入式
+關注
關注
5059文章
18975瀏覽量
302086 -
函數
+關注
關注
3文章
4284瀏覽量
62325 -
代碼
+關注
關注
30文章
4723瀏覽量
68237
原文標題:嵌入式C編碼規(guī)范
文章出處:【微信號:xiaojiaoyafpga,微信公眾號:電子森林】歡迎添加關注!文章轉載請注明出處。
發(fā)布評論請先 登錄
相關推薦
評論