? ? 關(guān)注、星標(biāo)公眾號(hào),直達(dá)精彩內(nèi)容 來(lái)源:網(wǎng)絡(luò)素材
編寫(xiě)代碼時(shí)最重要的一條規(guī)則是:檢查周圍的代碼并嘗試模仿它。
作為維護(hù)人員,如果收到的補(bǔ)丁明顯與周圍代碼的編碼風(fēng)格不同,這是令人沮喪的。這是不尊重人的,就像某人穿著泥濘的鞋子走進(jìn)一間一塵不染的房子。
因此,無(wú)論本文推薦的是什么,如果已經(jīng)編寫(xiě)了代碼并且您正在對(duì)其進(jìn)行修補(bǔ),請(qǐng)保持其當(dāng)前的樣式一致,即使它不是您最喜歡的樣式。
這里列出了最明顯和最重要的一般規(guī)則。在你繼續(xù)閱讀其他章節(jié)之前,請(qǐng)仔細(xì)檢查它們。
使用C99標(biāo)準(zhǔn)
不使用制表符,而是使用空格
每個(gè)縮進(jìn)級(jí)別使用4個(gè)空格
在關(guān)鍵字和左括號(hào)之間使用一個(gè)空格
在函數(shù)名和左括號(hào)之間不要使用空格
int32_t?a?=?sum(4,?3);??????????????/*?OK?*/
int32_t?a?=?sum?(4,?3);?????????????/*?Wrong?*/
不要在變量/函數(shù)/宏/類型中使用__或_前綴。這是為C語(yǔ)言本身保留的
對(duì)于嚴(yán)格的模塊私有函數(shù),使用prv_ name前綴
對(duì)于包含下劃線_ char的變量/函數(shù)/宏/類型,只能使用小寫(xiě)字母
左花括號(hào)總是與關(guān)鍵字(for, while, do, switch, if,…)在同一行
size_t?i;
for?(i?=?0;?i?5;?++i)?{???????????/*?OK?*/
}
for?(i?=?0;?i?5;?++i){????????????/*?Wrong?*/
}
for?(i?=?0;?i?5;?++i)?????????????/*?Wrong?*/
{
}
//?微信公眾號(hào):嵌入式大雜燴
int32_t?a;
a?=?3?+?4;??????????????/*?OK?*/
for?(a?=?0;?a?5;?++a)?/*?OK?*/
a=3+4;??????????????????/*?Wrong?*/
a?=?3+4;????????????????/*?Wrong?*/
for?(a=0;a<5;++a)???????/*?Wrong?*/
//?微信公眾號(hào):嵌入式大雜燴
func_name(5,?4);????????/*?OK?*/
func_name(4,3);?????????/*?Wrong?*/
static?int32_t?a;???????/*?OK?*/
static?int32_t?b?=?4;???/*?OK?*/
static?int32_t?a?=?0;???/*?Wrong?*/
void
my_func(void)?{
????static?int32_t*?ptr;/*?OK?*/
????static?char?abc?=?0;/*?Wrong?*/
}
void
my_func(void)?{
????char?a;?????????????/*?OK?*/
????char?b;?????????????/*?Wrong,?variable?with?char?type?already?exists?*/
????char?a,?b;??????????/*?OK?*/
}
i.自定義結(jié)構(gòu)和枚舉
ii.整數(shù)類型,更寬的無(wú)符號(hào)類型優(yōu)先
iii.單/雙浮點(diǎn)
int
my_func(void)?{
????/*?1?*/
????my_struct_t?my;?????/*?First?custom?structures?*/
????my_struct_ptr_t*?p;?/*?Pointers?too?*/
????/*?2?*/
????uint32_t?a;
????int32_t?b;
????uint16_t?c;
????int16_t?g;
????char?h;
????/*?...?*/
????/*?3?*/
????double?d;
????float?f;
}
/*?OK?*/
for?(size_t?i?=?0;?i?10;?++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)?...
void
a(void)?{
????/*?Avoid?function?calls?when?declaring?variable?*/
????int32_t?a,?b?=?sum(1,?2);
????/*?Use?this?*/
????int32_t?a,?b;
????b?=?sum(1,?2);
????/*?This?is?ok?*/
????uint8_t?a?=?3,?b?=?4;
}
除了char、float或double之外,始終使用stdint.h標(biāo)準(zhǔn)庫(kù)中聲明的類型。例如,8位的uint8_t等
不要使用stdbool.h庫(kù)。分別使用1或0表示真或假
/*?OK?*/
uint8_t?status;
status?=?0;
/*?Wrong?*/
#include?
bool?status?=?true;
永遠(yuǎn)不要與真實(shí)相比較。例如,使用if(check_func()){…}替換if (check_func() == 1)
總是將指針與空值進(jìn)行比較
void*?ptr;
/*?...?*/
/*?OK,?compare?against?NULL?*/
if?(ptr?==?NULL?||?ptr?!=?NULL)?{
}
/*?Wrong?*/
if?(ptr?||?!ptr)?{
}
int32_t?a?=?0;
...
a++;????????????/*?Wrong?*/
++a;????????????/*?OK?*/
for?(size_t?j?=?0;?j?10;?++j)?{}??/*?OK?*/
總是使用size_t作為長(zhǎng)度或大小變量
如果函數(shù)不應(yīng)該修改指針?biāo)赶虻膬?nèi)存,則總是使用const作為指針
如果不應(yīng)該修改函數(shù)的形參或變量,則總是使用const
/*?When?d?could?be?modified,?data?pointed?to?by?d?could?not?be?modified?*/
void
my_func(const?void*?d)?{
}
/*?When?d?and?data?pointed?to?by?d?both?could?not?be?modified?*/
void
my_func(const?void*?const?d)?{
}
/*?Not?required,?it?is?advised?*/
void
my_func(const?size_t?len)?{
}
/*?When?d?should?not?be?modified?inside?function,?only?data?pointed?to?by?d?could?be?modified?*/
void
my_func(void*?const?d)?{
}
/*
?*?To?send?data,?function?should?not?modify?memory?pointed?to?by?`data`?variable
?*?thus?`const`?keyword?is?important
?*
?*?To?send?generic?data?(or?to?write?them?to?file)
?*?any?type?may?be?passed?for?data,
?*?thus?use?`void?*`
?*/
/*?OK?example?*/
void
send_data(const?void*?data,?size_t?len)?{?/*?OK?*/
????/*?Do?not?cast?`void?*`?or?`const?void?*`?*/
????const?uint8_t*?d?=?data;/*?Function?handles?proper?type?for?internal?usage?*/
}
void
send_data(const?void*?data,?int?len)?{????/*?Wrong,?not?not?use?int?*/
}
總是使用括號(hào)和sizeof操作符
不要使用變長(zhǎng)數(shù)組。使用動(dòng)態(tài)內(nèi)存分配代替標(biāo)準(zhǔn)C malloc和自由函數(shù),或者如果庫(kù)/項(xiàng)目提供了自定義內(nèi)存分配,使用它的實(shí)現(xiàn)
看看LwMEM,一個(gè)自定義內(nèi)存管理庫(kù)。
/*?OK?*/
#include?
void
my_func(size_t?size)?{
????int32_t*?arr;
????arr?=?malloc(sizeof(*arr)?*?n);?/*?OK,?Allocate?memory?*/
????arr?=?malloc(sizeof?*arr?*?n);??/*?Wrong,?brackets?for?sizeof?operator?are?missing?*/
????if?(arr?==?NULL)?{
????????/*?FAIL,?no?memory?*/
????}
????free(arr);??/*?Free?memory?after?usage?*/
}
/*?Wrong?*/
void
my_func(size_t?size)?{
????int32_t?arr[size];??/*?Wrong,?do?not?use?VLA?*/
}
總是將variable與0進(jìn)行比較,除非它被視為布爾類型
永遠(yuǎn)不要將布爾處理的變量與0或1進(jìn)行比較。用NOT(!)代替
size_t?length?=?5;??/*?Counter?variable?*/
uint8_t?is_ok?=?0;??/*?Boolean-treated?variable?*/
if?(length)?????????/*?Wrong,?length?is?not?treated?as?boolean?*/
if?(length?>?0)?????/*?OK,?length?is?treated?as?counter?variable?containing?multi?values,?not?only?0?or?1?*/
if?(length?==?0)????/*?OK,?length?is?treated?as?counter?variable?containing?multi?values,?not?only?0?or?1?*/
if?(is_ok)??????????/*?OK,?variable?is?treated?as?boolean?*/
if?(!is_ok)?????????/*?OK,?-||-?*/
if?(is_ok?==?1)?????/*?Wrong,?never?compare?boolean?variable?against?1!?*/
if?(is_ok?==?0)?????/*?Wrong,?use?!?for?negative?check?*/
//This?is?comment?(wrong)
/*?This?is?comment?(ok)?*/
/*
?*?This?is?multi-line?comments,
?*?written?in?2?lines?(ok)
?*/
/**
?*?Wrong,?use?double-asterisk?only?for?doxygen?documentation
?*/
/*
*?Single?line?comment?without?space?before?asterisk?(wrong)
*/
/*
?*?Single?line?comment?in?multi-line?configuration?(wrong)
?*/
/*?Single?line?comment?(ok)?*/
void
my_func(void)?{
????char?a,?b;
????a?=?call_func_returning_char_a(a);??????????/*?This?is?comment?with?12*4?spaces?indent?from?beginning?of?line?*/
????b?=?call_func_returning_char_a_but_func_name_is_very_long(a);???/*?This?is?comment,?aligned?to?4-spaces?indent?*/
}
每個(gè)可以從模塊外部訪問(wèn)的函數(shù)都必須包含函數(shù)原型(或聲明)
函數(shù)名必須小寫(xiě),可以用下劃線_分隔
/*?OK?*/
void?my_func(void);
void?myfunc(void);
/*?Wrong?*/
void?MYFunc(void);
void?myFunc();
/*?OK?*/
const?char*?my_func(void);
my_struct_t*?my_func(int32_t?a,?int32_t?b);
/*?Wrong?*/
const?char?*my_func(void);
my_struct_t?*?my_func(void);
/*?OK,?function?names?aligned?*/
void????????set(int32_t?a);
my_type_t???get(void);
my_ptr_t*???get_ptr(void);
/*?Wrong?*/
void?set(int32_t?a);
const?char?*?get(void);
/*?OK?*/
int32_t
foo(void)?{
????return?0;
}
/*?OK?*/
static?const?char*
get_string(void)?{
????return?"Hello?world!\r\n";
}
/*?Wrong?*/
int32_t?foo(void)?{
????return?0;
}
/*?OK?*/
int32_t?a;
int32_t?my_var;
int32_t?myvar;
/*?Wrong?*/
int32_t?A;
int32_t?myVar;
int32_t?MYVar;
void
foo(void)?{
????int32_t?a,?b;???/*?OK?*/
????char?a;
????char?b;?????????/*?Wrong,?char?type?already?exists?*/
}
void
foo(void)?{
????int32_t?a;
????a?=?bar();
????int32_t?b;??????/*?Wrong,?there?is?already?executable?statement?*/
}
int32_t?a,?b;
a?=?foo();
if?(a)?{
????int32_t?c,?d;???/*?OK,?c?and?d?are?in?if-statement?scope?*/
????c?=?foo();
????int32_t?e;??????/*?Wrong,?there?was?already?executable?statement?inside?block?*/
}
/*?OK?*/
char*?a;
/*?Wrong?*/
char?*a;
char?*?a;
/*?OK?*/
char?*p,?*n;
結(jié)構(gòu)名或枚舉名必須小寫(xiě),單詞之間有下劃線_字符
結(jié)構(gòu)或枚舉可以包含typedef關(guān)鍵字
所有結(jié)構(gòu)成員都必須小寫(xiě)
所有枚舉成員必須是大寫(xiě)的
結(jié)構(gòu)/枚舉必須遵循doxygen文檔語(yǔ)法
在聲明結(jié)構(gòu)體時(shí),它可以使用以下三種不同的選項(xiàng)之一:
1、當(dāng)結(jié)構(gòu)體僅用名稱聲明時(shí),它的名稱后不能包含_t后綴。
struct?struct_name?{
????char*?a;
????char?b;
};
2、當(dāng)只使用typedef聲明結(jié)構(gòu)時(shí),它的名稱后面必須包含_t后綴。
typedef?struct?{
????char*?a;
????char?b;
}?struct_name_t;
3、當(dāng)結(jié)構(gòu)用name和typedef聲明時(shí),它不能包含_t作為基本名稱,它必須在它的名稱后面包含_t后綴作為typedef部分。
typedef?struct?struct_name?{
????char*?a;
????char?b;
????char?c;
}?struct_name_t;
錯(cuò)誤聲明的例子及其建議的糾正:
/*?a?and?b?must?be?separated?to?2?lines?*/
/*?Name?of?structure?with?typedef?must?include?_t?suffix?*/
typedef?struct?{
????int32_t?a,?b;
}?a;
/*?Corrected?version?*/
typedef?struct?{
????int32_t?a;
????int32_t?b;
}?a_t;
/*?Wrong?name,?it?must?not?include?_t?suffix?*/
struct?name_t?{
????int32_t?a;
????int32_t?b;
};
/*?Wrong?parameters,?must?be?all?uppercase?*/
typedef?enum?{
????MY_ENUM_TESTA,
????my_enum_testb,
}?my_enum_t;
/*?OK?*/
a_t?a?=?{
????.a?=?4,
????.b?=?5,
};
/*?Wrong?*/
a_t?a?=?{1,?2};
/*?Function?accepts?2?parameters?and?returns?uint8_t?*/
/*?Name?of?typedef?has?`_fn`?suffix?*/
typedef?uint8_t?(*my_func_typedef_fn)(uint8_t?p1,?const?char*?p2);
每個(gè)復(fù)合語(yǔ)句必須包括左花括號(hào)和右花括號(hào),即使它只包含1個(gè)嵌套語(yǔ)句
每個(gè)復(fù)合語(yǔ)句必須包含單個(gè)縮進(jìn);嵌套語(yǔ)句時(shí),每個(gè)嵌套包含1個(gè)縮進(jìn)大小
/*?OK?*/
if?(c)?{
????do_a();
}?else?{
????do_b();
}
/*?Wrong?*/
if?(c)
????do_a();
else
????do_b();
/*?Wrong?*/
if?(c)?do_a();
else?do_b();
/*?OK?*/
if?(a)?{
}?else?if?(b)?{
}?else?{
}
/*?Wrong?*/
if?(a)?{
}
else?{
}
/*?Wrong?*/
if?(a)?{
}
else
{
}
/*?OK?*/
do?{
????int32_t?a;
????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();
else?do_c();
if?(a)?do_a();?else?do_b();
/*?OK?*/
while?(is_register_bit_set())?{}
/*?Wrong?*/
while?(is_register_bit_set());
while?(is_register_bit_set())?{?}
while?(is_register_bit_set())?{
}
/*?Wait?for?bit?to?be?set?in?embedded?hardware?unit
uint32_t*?addr?=?HW_PERIPH_REGISTER_ADDR;
/*?Wait?bit?13?to?be?ready?*/
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?*/
/*?Not?recommended?*/
int32_t?a?=?0;
while?(a?10)?{
????.
????..
????...
????++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;
????}
}
/*?OK,?every?case?has?single?indent?*/
/*?OK,?every?break?has?additional?indent?*/
switch?(check())?{
????case?0:
????????do_a();
????????break;
????case?1:
????????do_b();
????????break;
????default:
????????break;
}
/*?Wrong,?case?indent?missing?*/
switch?(check())?{
case?0:
????do_a();
????break;
case?1:
????do_b();
????break;
default:
????break;
}
/*?Wrong?*/
switch?(check())?{
????case?0:
????????do_a();
????break;??????/*?Wrong,?break?must?have?indent?as?it?is?under?case?*/
????case?1:
????do_b();?????/*?Wrong,?indent?under?case?is?missing?*/
????break;
????default:
????????break;
}
/*?OK?*/
switch?(var)?{
????case?0:
????????do_job();
????????break;
????default:?break;
}
/*?Wrong,?default?is?missing?*/
switch?(var)?{
????case?0:
????????do_job();
????????break;
}
switch?(a)?{
????/*?OK?*/
????case?0:?{
????????int32_t?a,?b;
????????char?c;
????????a?=?5;
????????/*?...?*/
????????break;
????}
????/*?Wrong?*/
????case?1:
????{
????????int32_t?a;
????????break;
????}
????/*?Wrong,?break?shall?be?inside?*/
????case?2:?{
????????int32_t?a;
????}
????break;
}
/*?OK?*/
#define?MY_MACRO(x)?????????((x)?*?(x))
/*?Wrong?*/
#define?square(x)???????????((x)?*?(x))
/*?OK?*/
#define?MIN(x,?y)???????????((x)?(y)???(x)?:?(y))
/*?Wrong?*/
#define?MIN(x,?y)???????????x?
/*?Wrong?*/
#define?MIN(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))
typedef?struct?{
????int32_t?px,?py;
}?point_t;
point_t?p;??????????????????/*?Define?new?point?*/
/*?Wrong?implementation?*/
/*?Define?macro?to?set?point?*/
#define?SET_POINT(p,?x,?y)??(p)->px?=?(x);?(p)->py?=?(y)????/*?2?statements.?Last?one?should?not?implement?semicolon?*/
SET_POINT(&p,?3,?4);????????/*?Set?point?to?position?3,?4.?This?evaluates?to...?*/
(&p)->px?=?(3);?(&p)->py?=?(4);?/*?...?to?this.?In?this?example?this?is?not?a?problem.?*/
/*?Consider?this?ugly?code,?however?it?is?valid?by?C?standard?(not?recommended)?*/
if?(a)??????????????????????/*?If?a?is?true?*/
????if?(b)??????????????????/*?If?b?is?true?*/
????????SET_POINT(&p,?3,?4);/*?Set?point?to?x?=?3,?y?=?4?*/
????else
????????SET_POINT(&p,?5,?6);/*?Set?point?to?x?=?5,?y?=?6?*/
/*?Evaluates?to?code?below.?Do?you?see?the?problem??*/
if?(a)
????if?(b)
????????(&p)->px?=?(3);?(&p)->py?=?(4);
????else
????????(&p)->px?=?(5);?(&p)->py?=?(6);
/*?Or?if?we?rewrite?it?a?little?*/
if?(a)
????if?(b)
????????(&p)->px?=?(3);
????????(&p)->py?=?(4);
????else
????????(&p)->px?=?(5);
????????(&p)->py?=?(6);
/*
?*?Ask?yourself?a?question:?To?which?`if`?statement?`else`?keyword?belongs?
?*
?*?Based?on?first?part?of?code,?answer?is?straight-forward.?To?inner?`if`?statement?when?we?check?`b`?condition
?*?Actual?answer:?Compilation?error?as?`else`?belongs?nowhere
?*/
/*?Better?and?correct?implementation?of?macro?*/
#define?SET_POINT(p,?x,?y)??do?{?(p)->px?=?(x);?(p)->py?=?(y);?}?while?(0)????/*?2?statements.?No?semicolon?after?while?loop?*/
/*?Or?even?better?*/
#define?SET_POINT(p,?x,?y)??do?{????\???/*?Backslash?indicates?statement?continues?in?new?line?*/
????(p)->px?=?(x);??????????????????\
????(p)->py?=?(y);??????????????????\
}?while?(0)?????????????????????????????/*?2?statements.?No?semicolon?after?while?loop?*/
/*?Now?original?code?evaluates?to?*/
if?(a)
????if?(b)
????????do?{?(&p)->px?=?(3);?(&p)->py?=?(4);?}?while?(0);
????else
????????do?{?(&p)->px?=?(5);?(&p)->py?=?(6);?}?while?(0);
/*?Every?part?of?`if`?or?`else`?contains?only?`1`?inner?statement?(do-while),?hence?this?is?valid?evaluation?*/
/*?To?make?code?perfect,?use?brackets?for?every?if-ifelse-else?statements?*/
if?(a)?{????????????????????/*?If?a?is?true?*/
????if?(b)?{????????????????/*?If?b?is?true?*/
????????SET_POINT(&p,?3,?4);/*?Set?point?to?x?=?3,?y?=?4?*/
????}?else?{
????????SET_POINT(&p,?5,?6);/*?Set?point?to?x?=?5,?y?=?6?*/
????}
}
/*?OK?*/
#if?defined(XYZ)
#if?defined(ABC)
/*?do?when?ABC?defined?*/
#endif?/*?defined(ABC)?*/
#else?/*?defined(XYZ)?*/
/*?Do?when?XYZ?not?defined?*/
#endif?/*?!defined(XYZ)?*/
/*?Wrong?*/
#if?defined(XYZ)
????#if?defined(ABC)
????????/*?do?when?ABC?defined?*/
????#endif?/*?defined(ABC)?*/
#else?/*?defined(XYZ)?*/
????/*?Do?when?XYZ?not?defined?*/
#endif?/*?!defined(XYZ)?*/
文檔化的代碼允許doxygen解析和通用的html/pdf/latex輸出,因此正確地執(zhí)行是非常重要的。
/**
?*?\brief???????????Holds?pointer?to?first?entry?in?linked?list
?*??????????????????Beginning?of?this?text?is?5?tabs?(20?spaces)?from?beginning?of?line
?*/
static
type_t*?list;
/**
?*?\brief???????????This?is?point?struct
?*?\note????????????This?structure?is?used?to?calculate?all?point
?*??????????????????????related?stuff
?*/
typedef?struct?{
????int32_t?x;??????????????????????????????????/*!
????int32_t?y;??????????????????????????????????/*!
????int32_t?size;???????????????????????????????/*!????????????????????????????????????????????????????Since?comment?is?very?big,
????????????????????????????????????????????????????you?may?go?to?next?line?*/
}?point_t;
/**
?*?\brief???????????Point?color?enumeration
?*/
typedef?enum?{
????COLOR_RED,??????????????????????????????????/*!????????????????????????????????????????????????????spaces?offset?from?beginning?of?line?*/
????COLOR_GREEN,????????????????????????????????/*!
????COLOR_BLUE,?????????????????????????????????/*!
}?point_color_t;
函數(shù)的文檔必須在函數(shù)實(shí)現(xiàn)中編寫(xiě)(通常是源文件)
函數(shù)必須包括簡(jiǎn)要和所有參數(shù)文檔
如果每個(gè)參數(shù)分別為in或out輸入和輸出,則必須注意
如果函數(shù)返回某個(gè)值,則必須包含返回形參。這不適用于void函數(shù)
函數(shù)可以包含其他doxygen關(guān)鍵字,如note或warning
在參數(shù)名和描述之間使用冒號(hào):
/**
?*?\brief???????????Sum?`2`?numbers
?*?\param[in]???????a:?First?number
?*?\param[in]???????b:?Second?number
?*?\return??????????Sum?of?input?values
?*/
int32_t
sum(int32_t?a,?int32_t?b)?{
????return?a?+?b;
}
/**
?*?\brief???????????Sum?`2`?numbers?and?write?it?to?pointer
?*?\note????????????This?function?does?not?return?value,?it?stores?it?to?pointer?instead
?*?\param[in]???????a:?First?number
?*?\param[in]???????b:?Second?number
?*?\param[out]??????result:?Output?variable?used?to?save?result
?*/
void
void_sum(int32_t?a,?int32_t?b,?int32_t*?result)?{
????*result?=?a?+?b;
}
/**
?*?\brief???????????My?enumeration
?*/
typedef?enum?{
????MY_ERR,?????????????????????????????????????/*!
????MY_OK???????????????????????????????????????/*!
}?my_enum_t;
/**
?*?\brief???????????Check?some?value
?*?\return??????????\ref?MY_OK?on?success,?member?of?\ref?my_enum_t?otherwise
?*/
my_enum_t
check_value(void)?{
????return?MY_OK;
}
/**
?*?\brief???????????Get?data?from?input?array
?*?\param[in]???????in:?Input?data
?*?\return??????????Pointer?to?output?data?on?success,?`NULL`?otherwise
?*/
const?void?*
get_data(const?void*?in)?{
????return?in;
}
/**
?*?\brief???????????Get?minimal?value?between?`x`?and?`y`
?*?\param[in]???????x:?First?value
?*?\param[in]???????y:?Second?value
?*?\return??????????Minimal?value?between?`x`?and?`y`
?*?\hideinitializer
?*/
#define?MIN(x,?y)???????((x)?(y)???(x)?:?(y))
在文件末尾留下一個(gè)空行
每個(gè)文件都必須包括文件的doxygen注釋和后跟空行的簡(jiǎn)要描述(使用doxygen時(shí))
/**
?*?\file????????????template.h
?*?\brief???????????Template?include?file
?*/
????????????????????/*?Here?is?empty?line?*/
每個(gè)文件(頭文件或源文件)必須包含許可證(開(kāi)始注釋包括單個(gè)星號(hào),因?yàn)閐oxygen必須忽略這個(gè))
使用與項(xiàng)目/庫(kù)已經(jīng)使用的相同的許可證
/**
?*?\file????????????template.h
?*?\brief???????????Template?include?file
?*/
/*
?*?Copyright?(c)?year?FirstName?LASTNAME
?*
?*?Permission?is?hereby?granted,?free?of?charge,?to?any?person
?*?obtaining?a?copy?of?this?software?and?associated?documentation
?*?files?(the?"Software"),?to?deal?in?the?Software?without?restriction,
?*?including?without?limitation?the?rights?to?use,?copy,?modify,?merge,
?*?publish,?distribute,?sublicense,?and/or?sell?copies?of?the?Software,
?*?and?to?permit?persons?to?whom?the?Software?is?furnished?to?do?so,
?*?subject?to?the?following?conditions:
?*
?*?The?above?copyright?notice?and?this?permission?notice?shall?be
?*?included?in?all?copies?or?substantial?portions?of?the?Software.
?*
?*?THE?SOFTWARE?IS?PROVIDED?"AS?IS",?WITHOUT?WARRANTY?OF?ANY?KIND,
?*?EXPRESS?OR?IMPLIED,?INCLUDING?BUT?NOT?LIMITED?TO?THE?WARRANTIES
?*?OF?MERCHANTABILITY,?FITNESS?FOR?A?PARTICULAR?PURPOSE
?*?AND?NONINFRINGEMENT.?IN?NO?EVENT?SHALL?THE?AUTHORS?OR?COPYRIGHT
?*?HOLDERS?BE?LIABLE?FOR?ANY?CLAIM,?DAMAGES?OR?OTHER?LIABILITY,
?*?WHETHER?IN?AN?ACTION?OF?CONTRACT,?TORT?OR?OTHERWISE,?ARISING
?*?FROM,?OUT?OF?OR?IN?CONNECTION?WITH?THE?SOFTWARE?OR?THE?USE?OR
?*?OTHER?DEALINGS?IN?THE?SOFTWARE.
?*
?*?This?file?is?part?of?library_name.
?*
?*?Author:??????????FirstName?LASTNAME?
?*/
頭文件必須包含保護(hù)符#ifndef
頭文件必須包含c++檢查
在c++檢查之外包含外部頭文件
首先用STL C文件包含外部頭文件,然后是應(yīng)用程序自定義文件
頭文件必須包含其他所有頭文件,以便正確編譯,但不能包含更多頭文件(如果需要,.c應(yīng)該包含其余的頭文件)
頭文件必須只公開(kāi)模塊公共變量/類型/函數(shù)
在頭文件中使用extern作為全局模塊變量,稍后在源文件中定義它們
/*?file.h?...?*/
#ifndef?...
extern?int32_t?my_variable;?/*?This?is?global?variable?declaration?in?header?*/
#endif
/*?file.c?...?*/
int32_t?my_variable;????????/*?Actually?defined?in?source?*/
不要把.c文件包含在另一個(gè).c文件中
.c文件應(yīng)該首先包含相應(yīng)的.h文件,然后是其他文件,除非另有明確的必要
在頭文件中不包含模塊私有聲明
頭文件示例(示例中沒(méi)有l(wèi)icense)
/*?License?comes?here?*/
#ifndef?TEMPLATE_HDR_H
#define?TEMPLATE_HDR_H
/*?Include?headers?*/
#ifdef?__cplusplus
extern?"C"?{
#endif?/*?__cplusplus?*/
/*?File?content?here?*/
#ifdef?__cplusplus
}
#endif?/*?__cplusplus?*/
#endif?/*?TEMPLATE_HDR_H?*/
???????????????? ?END ????????????????
關(guān)注我的微信公眾號(hào),回復(fù)“加群”按規(guī)則加入技術(shù)交流群。
點(diǎn)擊“閱讀原文”查看更多分享,歡迎點(diǎn)分享、收藏、點(diǎn)贊、在看。