vxworks 编译规则Word文档下载推荐.docx
《vxworks 编译规则Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《vxworks 编译规则Word文档下载推荐.docx(15页珍藏版)》请在冰点文库上搜索。
addedcheckforinvalidindexinfooFind().
01a,10feb86,dnw
written.
*/
(在看vxworks的源码的时候会发现也是按此规则写的)
1.3C代码习惯
分成下面几个种类
l模块布局
l子程序布局
l代码布局
l命名习惯
l风格
l头文件布局
l文档生成
1.3.1C模块布局
一个模块是指在一个单一文件中的所有代码单元。
模块标题紧跟在文件标题之后,由以下几块组成,每一块之间由一个或几个空行隔开。
在更新历史之后和第一个函数或可执行的模块代码之前,如果需要,必须按照顺序包含下面的几个部分:
l模块文档概要:
由注释块组成,包含所有模块目的和功能的一个完整的描述,特别是外部接口。
包括相关的包含头文件。
格式为INCLUDEFILES:
文件列表。
l包含头文件:
由一个包含includes字样的单行注释加上一行或多行C的预处理宏#include组成。
这部分包含了本模块需要包含的所有头文件。
l定义:
由一个包含defines字样的单行注释加上一个或多个C的预处理宏#define组成。
这部分包含了本模块所需要的所有定义。
l类型:
由一个包含typedefs字样的单行注释加上一个或多个C的typedef声明组成。
这部分包含了本模块需要的所有类型定义。
l全局变量:
由一个包含globals字样的单行注释加上一个或多个C的全局定义组成,每行一个。
这部分包含了所有希望在本模块外能访问的变量的定义。
l本地变量:
由一个包含local字样的单行注释加上一个或多个C的局部定义组成,每行一个。
这部分包含了所有不希望在本模块外能访问的变量的定义。
l前向声明:
由一个包含forwarddeclarations字样的单行注释加上一个或多个ANSIC的函数原型声明组成,每行一个。
这部分包含了所有本模块中定义的函数原型。
前向声明仅仅用于本地函数,其它类型的函数在头文件中声明。
下面是一个例子,包含文件标题:
ExampleI-2:
CFileandModuleHeadings
*/
DESCRIPTION
ThismoduleisanexampleoftheWindRiverSystemsCcodingconventions.
...
INCLUDEFILES:
fooLib.h
/*includes*/
#include"
vxWorks.h"
fooLib.h"
/*defines*/
#defineMAX_FOOS
112
/*max#offooentries*/
#defineMIN_FATS
2
*min#ofFATcopies*/
/*typedefs*/
typedefstructfooMsg
/*FOO_MSG*/
{
VOIDFUNCPTRfunc;
/*pointertofunctiontoinvoke*/
intarg[FOO_MAX_ARGS];
/*argsforfunction*/
}FOO_MSG;
/*globals*/
char*
pGlobalFoo;
/*globalfootable*/
/*locals*/
LOCALintnumFoosLost;
/*countoffooslost*/
/*forwarddeclarations*/
LOCALint
fooMat(list*aList,intfooBar,BOOLdoFoo);
FOO_MSG
fooNext(void);
STATUS
fooPut(FOO_MSGinPar);
1.3.2C子程序布局
每一个子程序前面由一段C的注释标题组成,包含以下的几块。
标题中不能有空行,但是每一块必须由第一个字符是(*)且仅包含这个字符的单独一行分开。
lBanner:
表示注释的开始,由一个斜线(/)和75个星号(*)组成。
只有一行,包含子程序名和一段短的注释。
名称中的子程序名必须匹配声明中的子程序名。
l描述:
一个完整的描述,关于这个子程序的功能和如何使用。
l返回值:
单词RETURNS:
加上可能的返回值的描述。
如果没有返回值(声明时返回值为void),输入:
RETURNS:
N/A
l错误号:
单词ERRNO:
加上所有可能返回的错误号。
不用给出错误的描述,只需要写出错误号的值和常量定义的形式。
子程序标题用C语言的字符(*/)结束,必须另起一行,并从第一列开始。
ExampleI-3:
StandardCSubroutineLayout:
/********************************************************************
*
*fooGet-getanelementfromafoo
*Thisroutinefindstheelementofaspecifiedindexinaspecified
*foo.
Thevalueoftheelementfoundiscopiedto.
*RETURNS:
OK,orERRORiftheelementisnotfound.
*ERRNO:
*
S_fooLib_BLAH
S_fooLib_GRONK
STATUSfooGet
(
FOO
foo,
/*fooinwhichtofindelement*/
int
index,
/*elementtobefoundinfoo*/
int*
pvalue
/*wheretoputvalue*/
)
...
}
1.3.3C定义格式
一行只包含一个定义,并且必须符合当前的缩进水平。
变量
l基本变量:
首先是类型,然后插入一个制表符(TAB),最后是包含在一个单行注释中的描述。
例如:
unsigned
rootMemNBytes;
/*memoryforTCBandrootstack*/
int
rootTaskId;
/*roottaskID*/
BOOL
roundRobinOn;
/*booleanforround-robinmode*/
l指针变量的定义格式如下
FOO_NODE*
pFooNode;
/*foonodepointer*/
FOO_NODE**ppFooNode;
/*pointertothefoonodepointer*/
l结构的格式:
第一行是关键字struct加上结构名,下一行是开始的大括号,然后就是结构中的元素。
每一个元素占用单独的一行,并采用适当的缩进和注释。
如果需要,注释可以不止一行。
定义的结尾是一个反大括号,类型名字,分号。
记住,始终用typedef来声明这个结构或联合,并且包含结构名和类型名。
不要直接用结构定义去声明一个变量。
例:
typedefstructsymtab
/*SYMTAB-symboltable*/
OBJ_CORE
objCore;
/*objectmaintanance*/
HASH_ID
nameHashId;
/*hashtablefornames*/
SEMAPHORE
symMutex;
/*symboltablemutualexclusionsem*/
PART_ID
symPartId;
/*memorypartitionidforsymbols*/
BOOL
sameNameOk;
/*symboltablenameclashpolicy*/
nSymbols;
/*currentnumberofsymbolsintable*/
}SYMTAB;
这个格式也适用于其他的复合类型声明,例如联合或枚举。
不直接用结构定义去声明一个变量的例外是在结构中有一个指向结构的指针,隐
含着另外一种类型声明。
这种情况允许结构存储相关的结构指针而不需要包含定义那种类型的头文件。
例如,下面的例子可以编译通过而不需要包含定义类型structfooInfo的头文件
CORRECT:
typedefstructtcbInfo
{
structfooInfo*
pfooInfo;
}
TCB_INFO;
相反,下面的例子如果不包含定义类型FOO_INFO的头文件就不能通过编译。
INCORRECT:
FOO_INFO*
子程序:
子程序的声明有两种格式,取决于子程序是否带参数。
l如果子程序带参数,第一行是返回类型和子程序名,第二行是括号,接着就是传给子程序的参数,每行一个,最后包含一个反括号的单独一行表示子程序声明的结束。
intlstFind
LIST*
pList,
/*listinwhichtosearch*/
NODE*
pNode
/*pointertonodetosearchfor*/
)
l如果子程序不带参数,就只占用一行的空间,并且括号之间必须有一个关键字void。
STATUSfppProbe(void)
1.3.4C代码布局
每一行代码的最大长度为80个字符,包含以下内容:
l垂直间隔
l水平间隔
l缩进
l注释
垂直间隔
l使用空行使代码更容易阅读,并且把逻辑上相关的部分放在一起。
在注释行的前后分别放置一个空行。
l不要在一行放置多个声明,每一个变量和函数的参数必须在一个单独的行中声明,不要使用逗号列表去声明多个变量。
l不要在一行中放置多个表达式,但是for表达式例外,
for(i=0;
i<
count;
i++)
或者在switch表达式中动作很短并且几乎一样也可以放在同一行中。
在if表达式中,执行部分总是相对于条件表达式另起一行。
if(i>
count)
i=count;
l括号({和})和case标记总是占用它们自己的一行。
水平间隔
l在二元操作符两边,逗号后面,括号前面放置空格,不要在结构成员和指针操作符两边放置空格。
在数组的第一个括号前放置空格,但是如果数组里面只有一到两个字符的话,该空格可以省略。
status=fooGet(foo,i+3,&
value);
foo.index
pFoo->
index
fooArray[(max+min)/2]
string[0]
l一行写不下的按照下面的格式排列:
a=(b+c)*
(d+e);
status=fooList(foo,a,b,c,
d,e);
if((a==b)&
&
(c==d))
...
缩进
l缩进的间隔是4个字符(即第1,5,9,13列)
l模块和子程序的标题以及子程序的声明从第一列开始
l下列情况进行缩进
子程序声明
条件表达式
循环表达式
switch表达式
case标记
typedef后面的结构定义
lelse的缩进方式与if一样,例如:
if(condition)
statements
}
else
elseif的缩进方式:
if(condition)
elseif(condition)
lswitch表达式的缩进方式:
switch(input)
case'
a'
:
...
break;
b'
default:
如果执行的动作很短而且几乎所有的动作都相同,可以采用下面的形式:
x=aVar;
x=bVar;
c'
x=cVar;
x=defaultVar;
l所有的注释都有相同的缩进方式
l括号({和})的缩进方式和它前后的代码相同
注释
l注释应该放在相关的代码前面,并且缩进的水平应该相同。
在注释和代码之间用一个单独的空行隔开。
?
单行注释的格式如下:
/*Thisisthecorrectformatforasingle-linecomment*/
foo=MAX_FOO;
如果是多行注释,开始和结束的注释标识应该单起一行,每一行注释的前面放置一个星号(*),如下:
*Thisisthecorrectformatforamultilinecomment
*inasectionofcode.
foo=MIN_FOO;
l声明中和代码后部的多行注释由一个或多个单行注释组成,例如:
intfoo
a,
/*thisisthecorrectformatfora*/
/*multilinecommentinadeclaration*/
b
/*standardcommentattheendofaline*/
day=night;
/*whennecessary,acommentaboutaline*/
/*ofcodecanbedonethisway*/
1.3.5C命名习惯
l当创建名字的时候,记住这段代码只会写一次,但是可能有很多人来阅读。
所以应该取一个有意义的和易读的名字,不要使用模糊的缩写。
l程序名、变量名、结构或联合的成员变量名由大写和小写字母组成,不要使用下划线。
每个单词的首字母大写,但第一个字母除外。
aVariableName
l类型,常量和宏的定义全部由大写字母组成,每个单词间用下滑线隔开
A_CONSTANT_value
l每一个模块都有一个短的前缀,2到5个字符。
所有外部会用到的子程序,变量,常量,宏和类型的前面都要加上这个前缀。
(外部不会用到的不用遵循这个习惯)。
fooLib.c
modulename
fooObjFind
subroutinename
FooCount
variablename
FOO_MAX_COUNT
constant
FOO_NODE
type
l子程序名遵循模块-名词-动词的规则,首先是模块名前缀,然后是该程序要处理的东西或对象的名字,最后是该程序要使用的动作。
foo-object-find
sysNvRamGet
system-NVRAM-get
taskSwitchHookAdd
task-switchhook-add
l每一个头文件会定义一个预处理用的符号以防止该文件被多次包含。
这个符号的格式是该文件名加上前缀__INC(去掉.)。
__INCfooLibh
l指针变量名的前面加上一个前缀p,多级指针就加多个。
FOO_NODE**
ppFooNode;
FOO_NODE***
pppFooNode;
1.3.6C风格
附加的编程风格。
l注释:
不要使用不完全的注释
l数字常量:
使用#define来定义常量,并为该常量取一个好的名字。
不要在代码或声明中使用数字常量(除了很明显的小数字例如1或者0)。
l布尔测试:
当你测试一个布尔类型时不要使用非布尔类型的测试。
例如,如果X是一个整数:
正确:
if(x==0)
不正确:
if(!
x)
相似的,当你测试一个非布尔类型时不要使用布尔类型的测试。
例如,如果libInstalled是一个布尔变量:
if(libInstalled)
if(libInstalled==TRUE)
l私有接口:
私有接口指的是应用程序或库内部使用的函数和数据,不会作为外部接口的一部分的。
私有接口应该放置在一个单独的头文件中,位于目录private下。
该头文件名的最后一个字母是大写的P。
例如,库blahlib用到的私有函数原型和数据放在文件private/private/blahLibP.h中。
l结构的传递和返回:
总是使用指针的形式,不要直接使用结构本身。
l状态返回值:
返回状态值的函数应该返回OK或者ERROR(在vxworks.h中定义)。
特殊的错误类型由errno的值描述。
不返回任何值的函数应该返回void。
l使用定义好的名字:
尽可能的使用在vxworks.h中定义好的名字,