0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

嵌入式系统中C语言的编写规范

嵌入式开发星球 来源:嵌入式开发爱好者 作者:嵌入式开发爱好者 2024-05-11 08:49 次阅读

最重要的一条规则

编写代码时最重要的一条规则是:检查周围的代码并尝试模仿它。

作为维护人员,如果收到的补丁明显与周围代码的编码风格不同,这是令人沮丧的。这是不尊重人的,就像某人穿着泥泞的鞋子走进一间一尘不染的房子。

因此,无论本文推荐的是什么,如果已经编写了代码并且您正在对其进行修补,请保持其当前的样式一致,即使它不是您最喜欢的样式。

一般规则

这里列出了最明显和最重要的一般规则。在你继续阅读其他章节之前,请仔细检查它们。

使用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;i<  5; ++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;a<  5; ++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*/
  • 不要初始化静态和全局变量为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.整数类型,更宽的无符号类型优先

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;}
  • 总是在块的开头声明局部变量,在第一个可执行语句之前
  • 在for循环中声明计数器变量
/*OK*/for(size_ti=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) ...
  • 避免在声明中使用函数调用来赋值变量,除了单个变量
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*/#includeboolstatus=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;j<  10; ++j) {}  /* OK */

总是使用size_t作为长度或大小变量

如果函数不应该修改指针所指向的内存,则总是使用const作为指针

如果不应该修改函数的形参或变量,则总是使用const

/*Whendcouldbemodified,datapointedtobydcouldnotbemodified*/voidmy_func(constvoid*d){}/*Whendanddatapointedtobydbothcouldnotbemodified*/voidmy_func(constvoid*constd){}/*Notrequired,itisadvised*/voidmy_func(constsize_tlen){}/*Whendshouldnotbemodifiedinsidefunction,onlydatapointedtobydcouldbemodified*/voidmy_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操作符

不要使用变长数组。使用动态内存分配代替标准C malloc和自由函数,或者如果库/项目提供了自定义内存分配,使用它的实现

看看LwMEM,一个自定义内存管理库。

/*OK*/#includevoidmy_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*/voidmy_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注释,即使函数是静态的

使用英文名称/文本的函数,变量,注释

变量使用小写字母

如果变量包含多个名称,请使用下划线。force_redraw。不要使用forceRedraw

对于C标准库的包含文件,请始终使用<和>。例如,# include < stdlib.h >

对于自定义库,请始终使用""。例如,# include“my_library.h”

当转换为指针类型时,总是将星号与类型对齐,例如。uint8_t* t = (uint8_t*)var_width_diff_type

始终尊重项目或库中已经使用的代码风格

注释

  • 不允许以//开头的注释。总是使用/* comment */,即使是单行注释
//Thisiscomment(wrong)/*Thisiscomment(ok)*/
  • 对于多行注释,每行使用空格+星号
/**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*/}

函数

每个可以从模块外部访问的函数都必须包含函数原型(或声明)

函数名必须小写,可以用下划线_分隔

/*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_tfoo(void){return0;}/*OK*/staticconstchar*get_string(void){return"Helloworld!rn";}/*Wrong*/int32_tfoo(void){return0;}

变量

  • 使变量名全部小写,下划线_字符可选
/*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*/}
  • 不要在第一个可执行语句之后声明变量
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;

结构、枚举类型定义

结构名或枚举名必须小写,单词之间有下划线_字符

结构或枚举可以包含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};
  • 当为函数句柄引入new typedef时,使用_fn后缀
/*Functionaccepts2parametersandreturnsuint8_t*//*Nameoftypedefhas`_fn`suffix*/typedefuint8_t(*my_func_typedef_fn)(uint8_tp1,constchar*p2);

复合语句

每个复合语句必须包括左花括号和右花括号,即使它只包含1个嵌套语句

每个复合语句必须包含单个缩进;嵌套语句时,每个嵌套包含1个缩进大小

/*OK*/if(c){do_a();}else{do_b();}/*Wrong*/if(c)do_a();elsedo_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循环、do-while循环或for循环必须包含花括号
/*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等)为空(嵌入式编程中也可能是这种情况),请使用空的单行括号
/*Waitforbittobesetinembeddedhardwareunituint32_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 */
  • 尽量避免在循环块内递增变量,参见示例
/*Notrecommended*/int32_ta=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;    }}

分支语句

为每个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;}

宏和预处理指令

  • 总是使用宏而不是文字常量,特别是对于数字
  • 所有的宏必须是全大写的,并带有下划线_字符(可选),除非它们被明确标记为function,将来可能会被常规函数语法替换
/*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 <  y ? x : y
  • 总是用括号保护最终的宏计算
/*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*/elseSET_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);elsedo{(&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输出,因此正确地执行是非常重要的。

  • 对变量、函数和结构/枚举使用doxygen支持的文档样式
  • 经常使用作为doxygen,不要使用@
  • 始终使用5x4空格(5个制表符)作为文本行开始的偏移量
/***briefHoldspointertofirstentryinlinkedlist*Beginningofthistextis5tabs(20spaces)frombeginningofline*/statictype_t*list;
  • 每个结构/枚举成员都必须包含文档
  • 注释的开头使用12x4空格偏移量
/***briefThisispointstruct*noteThisstructureisusedtocalculateallpoint*relatedstuff*/typedefstruct{int32_tx;/*!<  Point X coordinate */    int32_t y;                                  /*!<  Point Y coordinate */    int32_t size;                               /*!<  Point size.                                                    Since comment is very big,                                                    you may go to next line */} point_t;/** * brief           Point color enumeration */typedef enum {    COLOR_RED,                                  /*!<  Red color. This comment has 12x4                                                    spaces offset from beginning of line */    COLOR_GREEN,                                /*!<  Green color */    COLOR_BLUE,                                 /*!<  Blue color */} point_color_t;

函数的文档必须在函数实现中编写(通常是源文件)

函数必须包括简要和所有参数文档

如果每个参数分别为in或out输入和输出,则必须注意

如果函数返回某个值,则必须包含返回形参。这不适用于void函数

函数可以包含其他doxygen关键字,如note或warning

在参数名和描述之间使用冒号:

/***briefSum`2`numbers*param[in]a:Firstnumber*param[in]b:Secondnumber*returnSumofinputvalues*/int32_tsum(int32_ta,int32_tb){returna+b;}/***briefSum`2`numbersandwriteittopointer*noteThisfunctiondoesnotreturnvalue,itstoresittopointerinstead*param[in]a:Firstnumber*param[in]b:Secondnumber*param[out]result:Outputvariableusedtosaveresult*/voidvoid_sum(int32_ta,int32_tb,int32_t*result){*result=a+b;}
  • 如果函数返回枚举的成员,则使用ref关键字指定哪个成员
/***briefMyenumeration*/typedefenum{MY_ERR,/*!<  Error value */    MY_OK                                       /*!<  OK value */} my_enum_t;/** * brief           Check some value * return          ref MY_OK on success, member of ref my_enum_t otherwise */my_enum_tcheck_value(void) {    return MY_OK;}
  • 对常量或数字使用符号(' NULL ' => NULL)
/***briefGetdatafrominputarray*param[in]in:Inputdata*returnPointertooutputdataonsuccess,`NULL`otherwise*/constvoid*get_data(constvoid*in){returnin;}
  • 宏的文档必须包括hideinitializer doxygen命令
/***briefGetminimalvaluebetween`x`and`y`*param[in]x:Firstvalue*param[in]y:Secondvalue*returnMinimalvaluebetween`x`and`y`*hideinitializer*/#defineMIN(x,y)((x)<  (y) ? (x) : (y))

头/源文件

在文件末尾留下一个空行

每个文件都必须包括文件的doxygen注释和后跟空行的简要描述(使用doxygen时)

/***filetemplate.h*briefTemplateincludefile*//*Hereisemptyline*/

每个文件(头文件或源文件)必须包含许可证(开始注释包括单个星号,因为doxygen必须忽略这个)

使用与项目/库已经使用的相同的许可证

/***filetemplate.h*briefTemplateincludefile*//**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*/

头文件必须包含保护符#ifndef

头文件必须包含c++检查

在c++检查之外包含外部头文件

首先用STL C文件包含外部头文件,然后是应用程序自定义文件

头文件必须包含其他所有头文件,以便正确编译,但不能包含更多头文件(如果需要,.c应该包含其余的头文件)

头文件必须只公开模块公共变量/类型/函数

在头文件中使用extern作为全局模块变量,稍后在源文件中定义它们

/*file.h...*/#ifndef...externint32_tmy_variable;/*Thisisglobalvariabledeclarationinheader*/#endif/*file.c...*/int32_tmy_variable;/*Actuallydefinedinsource*/

不要把.c文件包含在另一个.c文件中

.c文件应该首先包含相应的.h文件,然后是其他文件,除非另有明确的必要

在头文件中不包含模块私有声明

头文件示例(示例中没有license)

/*Licensecomeshere*/#ifndefTEMPLATE_HDR_H#defineTEMPLATE_HDR_H/*Includeheaders*/#ifdef__cplusplusextern"C"{#endif/*__cplusplus*//*Filecontenthere*/#ifdef__cplusplus}#endif/*__cplusplus*/#endif/*TEMPLATE_HDR_H*/


审核编辑 黄宇

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 嵌入式
    +关注

    关注

    5003

    文章

    18429

    浏览量

    291789
  • C语言
    +关注

    关注

    180

    文章

    7549

    浏览量

    131457
  • 人工智能
    +关注

    关注

    1780

    文章

    44713

    浏览量

    231685
  • 代码
    +关注

    关注

    30

    文章

    4578

    浏览量

    67171
收藏 人收藏

    评论

    相关推荐

    如何成为一名嵌入式C语言高手?

    相关教材、参加在线课程或者参考编程书籍来系统地学习C语言的基础知识,并通过编写简单的程序进行实践。 二、深入了解嵌入式
    发表于 03-25 14:12

    如何成为一名嵌入式C语言高手?

    相关教材、参加在线课程或者参考编程书籍来系统地学习C语言的基础知识,并通过编写简单的程序进行实践。 二、深入了解嵌入式
    发表于 04-07 16:03

    C语言嵌入式系统编程技巧

    过程的复杂性,它并不是嵌入式系统开发的一般选择。而与之相比,C语言--一种"高级的低级"语言,则成为嵌入
    发表于 12-23 10:40

    如何学习C语言嵌入式系统编程

    系统开发的一般选择。而与之相比,C语言--一种"高级 的低级"语言,则成为嵌入式系统开发的佳选择
    发表于 11-11 19:55

    嵌入式Linux C代码规范

    本文档为作者 在嵌入式嵌入式 linux C语言的学习和工作中所总结的代码规范 ,是作者从 STM32单片机开发向 Linux
    发表于 01-14 10:25

    【原创分享】如何学好嵌入式系统C语言编程

    各个环节的作用,才能对嵌入式系统C编程有深入的认识。另一个问题是,虽然C语言是一门高级语言,但是
    发表于 09-28 20:37

    嵌入式C语言C语言的区别

    嵌入式C语言C语言的区别:最常用的系统编程语言
    发表于 10-27 06:52

    基于ARM的嵌入式系统C语言编程的结合

    嵌入式平台上进行C语言编写系统软件和应用软件的方法,希望为软件编程人员提供一些思考。随着计算机技术尤其是计算机信息控制技术的深入发展,
    发表于 12-14 08:49

    标准C语言嵌入式C语言有哪些区别

    世界使用最广泛的系统编程语言嵌入式CC的扩展,在嵌入式
    发表于 12-14 06:15

    适合于嵌入式系统C语言单元测试框架是什么

    工程没有合适的测试框架。本文发布一种简单的C语言测试框架CUNIT,可以应用于嵌入式领域。测试环境本框架是基于标准C
    发表于 12-15 08:10

    嵌入式系统的Python与C / C ++的相关资料分享

    嵌入式python c++ 尽管C / C ++编程语言有很多缺点,但它们在嵌入式
    发表于 12-15 07:14

    怎么样用C语言编写嵌入式系统的死循环呢

    怎么样用C语言编写嵌入式系统的死循环呢?关键字volatile有什么含义吗?
    发表于 12-24 07:46

    嵌入式C语言的知识点汇总,绝对实用

    1 嵌入式C语言总结从语法上来说C语言并不复杂, 但编写优质可靠的
    发表于 02-17 06:10

    嵌入式C语言进阶之道

    的。问题是,若是我不愿意只是当一个小菜鸟,我想对嵌入式 C 语言有 更多更深的了解时,我突然发现,满图书馆的书,竟找不到一本,能解我心头之惑。 对于在实际工作当中, 你不再是独自编写
    发表于 04-19 10:15

    嵌入式系统中C语言编写规范

    如果变量包含多个名称,请使用下划线。force_redraw。不要使用forceRedraw 对于C标准库的包含文件,请始终使用。例如,# include < stdlib.h >
    发表于 03-15 09:55 194次阅读