C语言编程规范V
C语言编程规范-V1.0
一、文件命名
1.文件主名以字母开头,由字母、数字或下划线组成
2.采用下列文件名后缀:
.c(C程序文件)
.h(头文件)
.o(可重载目标文件)
.a(静态库)
.sl(动态库)
注:与特定编译器缺省后缀约定冲突的,遵循编译器的缺省后缀约定
3.编辑工具make的控制文件取名makefile
4.自述文件取名readme
二、源程序文件
1.源程序文件段落依照下列顺序:
序言
系统头文件引用(include)
用户头文件引用(include)
全局常量宏定义(define)
全局函数宏定义(define)
全局类型定义(typedef)
全局枚举类型定义(enums)
全局变量说明(extern)
全局变量说明(non-static)
全局变量说明(static)
函数(通常从最高层开始,按层次横向排列。如果定义较多的独立的公用函数,可以考虑按字母顺序排列)
2.序言内容应包括版权声明、文件名、内容描述、版本历史,格式如下:
/*
* Copyright 2014,XXX Co., Ltd. All right reserved.
* This program prints out messages from a queue.
* Edit History:
* 2014/11/28 - Created by GaoXuefeng.
* 2014/11/29 - Modified by ChenChen to print output in the new form.
*/
3.段落之间用空行分隔
4.文件长度尽可能在1000行之内
5.每行长度尽可能不要超过79列
三、头文件
1.用户头文件名避免使用系统头文件名
2.按照功能组织头文件,例如独立的子系统应单独一个头文件
3.与机器相关的说明组成单独头文件
4.多个源文件引用的说明放入头文件中
5.头文件不要嵌套
6.说明函数或外部变量的头文件应在定义该函数或变量的文件中引用
7.不要在头文件中定义变量
8.内部使用的宏、枚举、结构定义不应放入头文件中
9.内部使用的函数(相当于类的私有方法)声明不应放在头文件中
10.只引用需要的头文件
11.每个头文件采用下面的形式避免被重复引用:
#ifndef EXAMPLE_H
#define EXAMPLE_H
...... /* body of example.h file */
#endif /* EXAMPLE_H */
12.引用头文件不要使用绝对路径。使用
引用用户头文件,并使用C编译器的–I选项指出路径
四、其他文件
1.编写“readme”文件,列出条件编译开关、与机器相关的文件等信息
五、注释
1.用注释块描述数据结构、算法等,放在被注释的程序段前:
/*
* Here is a block comment.
* The opening slash-star and closing star-slash are alone on a line.
* ...
*/
2.单行注释放在被注释的程序段前,并与该程序段对齐:
if (argc > 1) {
/* Get input file frmm command line */
if (freopen(argv[1], "r", stdin) == NULL) {
perror(argv[1]);
}
}
3.放在代码行尾的“短注释”应从第9、13、17、21、25、……列开始,并与被注释的代
码分开至少一个空格。如果在一段代码中出现多处短注释,这些短注释应相互对齐: if (a == EXCEPTION) {
b = TRUE; /* special case */
} else {
b = isprime(a); /* works only for odd a */
}
4.除非必要,不应在一行代码或表达式的中间插入注释
5.重要的函数、复杂的函数、提供给外部使用的接口函数应编写详细的注释
6.全局变量要有较详细的注释,包括对其功能、取值范围以及存取时注意事项的说明
7.修改代码时,应维护代码周边的所有注释,以保证注释与代码的一致性
六、说明(declaration)
1.外部数据说明明使用关键字extern
2.如果在外部数组定义时,显式地定义了其大小,则在该外部数据说明时应重复定义其大
小:
In file1:
extern int x[SIZE]; /* should not use x[] */
void foo(void) {...};
In file2:
int x[SIZE];
3.指针修饰符“*”应与变量名在一起,而不要与变量类型在一起:
char *s, *t, *u;
下列写法不正确:
char* s, t, u;
4.不相关的多个说明,即使是同一类型,也不要写在同一行
5.对每个变量和结构中的每个元素要加以短注释
6.结构中的花括号的用法采用K&R的紧凑格式
7.初值具有意义的变量在定义的同时应显式初始化,或至少应加以注释说明缺省初始化为
零:
int x = 1;
int y; /* initial value is 0 */
char *msg = “message”;
8.用长型常量初始化长型变量
9.使用大写字母“L”表示长型常量
10.如果一个程序由多个文件组成,在任何一个文件中尽可能利用static把函数和变量的作
用域限制在本文件中(使用static确保变量只是在声明它的文件中是可见的,并且避免了和其他文件或库中的相同标识符发生混淆的可能性)
11.除非不得已,应尽可能避免访问其他文件的变量。访问其他文件的变量时应加以注释,
指出变量所在文件的名称
12.用typedef定义最重要的数据类型,即便它们只是整数
13.可以在说明结构的同时定义结构类型,两者取同名:
typedef struct splodge_t {
int sp_count;
char *sp_name;
char *sp_alias;
} splodge_t;
七、函数说明
1.每个函数前加入注释块,描述函数功能、输入参数和返回值,必要时应说明其功能、用
法、重要设计决策与副作用
/*
* Function: PrintOneMsg
* To print out one message from a queue
* Parameters:
* msgno - message number
* qid - message queue identifier
* Return Value:
* 0 - success
* -1 - failure
*/
int PrintOneMsg((int msgno, int qid)
{
function body;
}
2.不要省略函数返回类型;如果函数无返回值,使用void作为函数返回类型
3.函数应避免使用全局变量、静态局部变量和I/O操作,不可避免的地方应集中使用
4.函数的参数个数尽可能不要超过5个
5.函数体的开、闭花括号写在第一列,分别占一行。函数体的局部变量说明和代码缩进4
格
6.如果一组函数含有一个相同的参数或局部变量,则每个函数以相同的变量名引用这个变
量,并出现在参数表相同的位置
7.不同含义的变量即使在不同的相关函数中,也不要使用相同的变量名
8.局部变量说明与函数的语句以一行空行分开
八、空格和空行
1.空格和空行应反映代码的块结构。例如:每个函数之间空1行,函数内每个程序段空1
行,每个层次缩进4格
2.缩格一律使用空格键,而不要用制表键
3.关键字与带括号的表达式间插入一个空格(sizeof例外)
4.在变量表中,逗号后插入一个空格
5.宏函数名与左括号之间不要有空格
6.换行时应一个完整的语句放在一行,不要根据字符数断行
九、简单句
1.每行仅书写一条语句。在for或while循环中,如果循环体为空,空循环体应占一行并
加注释:
while (*dest++ = src++)
; /* void */
2.除下条规定的情况以外,其他情况不要在条件表达式中使用隐式的非零检测,例如
if (f() != FAIL)
不应写成
if (f())
3.对满足以下全部条件的函数可以使用隐式的非零检测:
函数值取零时表示假
函数名明显地表示真值:isdigit()、isvalid()、alid()
4.必要时可以在公共头文件中定义:
#define FALSE 0
#define TRUE 1
5.不要检测布尔值等于1(TRUE),例如
if (f() != FAIL)
不应写成
if (f() == TRUE)
6.慎用嵌入式赋值语句,例如下列写法是一种不好的风格:
d = (a = b + c) + r;
但下列写法是允许的:
while ((c = getchar()) != EOF) {
process the character
}
7.慎用goto语句。通常仅用于中断多层嵌套的switch、for、while语句,并加以注释:
/* broken out into errro handling when disaster */
for (...) {
while (...) {
...
if (disaster)
goto error;
}
}
error:
clean up the mess;
十、复合语句
1.复合句花括号的书写格式采用K&R紧凑风格:
开括号与相应的关键字同行
if-else语句的else部分与闭括号同行
do-while语句的while部分与闭括号同行
https://www.360docs.net/doc/915888816.html,bel语句单独一行(除非在一个程序块中有许多label)
3.在switch语句中出现的fall-through应加以注释:
switch (expr) {
case ABC:
case DEF:
statement;
break;
case UVW:
statement;
/* fall-through */
case XYZ:
statement;
break;
}
4.在switch语句中的最后一个case结束处也需使用braek语句
5.如果switch语句含default case,它应出现在最后,但不需要break语句。在switch语句
的default case使用注释列出可能的取值。在if-else语句中,如果if或else部分是复合句,则if和else部分无论是复合句还是简单句均加上花括号:
if (expr) {
statement;
} else {
statement;
statement;
}
6.带else if的 if-else语句中的else条件应左对齐:
if (...) {
statement;
...
} else if (...) {
statement;
...
} else if (...) {
statement;
...
} else {
statement for default;
...
}
7.do-while语句的循环体总是加上花括号
8.如果if产生无条件转出(break、continue、goto、return),则else应该是隐含的,且不
需要缩进:
if (level > limit)
return (OVERFLOW);
normal();
return (level);
十一、运算符及表达式
1.单目操作符不要与它的操作数分开。双目操作符除“.”和“->”外一般应与它的操作
数用空格分开。但对于较复杂的表达式,如果里层的操作符不用空格与它的操作数分开,可能更清晰
2.对于复杂的表达式,可以分成若干行,并尽可能在最低运算顺序的操作符前断行,且后
续行缩进4个空格。涉及多种操作符的表达式,尽可能利用圆括号强调运算顺序
3.对于取离散数值的变量,不要用float类型
4.float变量的比较使用“<=”或“>=”,而不要用“==”或“!=”
5.用括号明确表达式的操作顺序,避免过分依赖默认优先级
十二、基本命名约定
1.以下划线开头或结尾的名字是系统保留的,应用程序应避免用来命名自己的名字
2.#define常量名应全部大写
3.Enum常量名应全部大写
4.函数名、typedef名和变量名(包括struct、union、enum),除了常见的通用缩写以外,
不使用单词缩写,不得使用汉语拼音,命名法可采用以下三种常用命名法之一:
Unix like命名法,单词用小写字母,每个单词直接用下划线分割,例如text_mutex,kernel_text_address
骆驼式命名法,第一个单词小写,其余单词首字母大写,单词都连结在一起
帕斯卡命名法,第一个单词首字母采用大写字母,后续单词的首字母亦采用大写字母,单词都连结在一起
注:同一应用程序只能使用一种命名法
5.宏函数名应全部大写
6.避免仅用大小写或下划线区分相似的标识符,如foo和FOO、foobar和foo_bar
7.typedef名通常以“_t”结尾
8.避免看上去不易区分的标识符,如:1(一),l(小写L),I(大写i)
9.避免标识符完全相同的局部变量和全局变量。特别地,避免以标准库中的名字来命名应
用系统中的名字
10.变量名应使用“名词”或“形容词+名词”
11.函数名应使用“动词”或“动词+名词”(动宾词组)
12.避免标识符出现数字编号,除非逻辑上确实需要编号
十三、常量
1.不要在程序中直接写数值,而通过#define给其一个有意义的标识符,然后在程序中引
用。但在某些场合,0和1可以直接使用,如作为循环的初值
2.取离散数值的变量最好定义为enum数据类型
3.常量的定义应与它们的用途一致。例如,对于浮点数,常量540应定义为540.0
4.对于空指针值,应使用NULL,而不要使用0
5.如果某一常量与其他常量密切相关,应在定义中包含这种关系,例如:
#define RADIUS = 100;
#define DIAMETER = RADIUS * 2;
十四、条件编译
1.用#ifdef定义条件编译依赖的机器时,如果未指定机器,应产生错误(使用#error),而
不是缺省机器
2.用#ifdef定义优化时,缺省应为非优化
金卡工程城市卡运营联盟TSM平台运营公司(筹)
2014年12月08日