【C/C++】C语言编程规范
C语言编码规范
参考Linux kernel代码规范,社区对于C语言编码做如下要求:
缩进
● 使用Tab作为行首缩进,而不是空格。Tab Size设为4字符
● switch语句中,case不缩进
switch (var) {
case 0:
break;
case 1:
break;
default:
break;
}
换行
● 每行不超过80字符
● 超过80字符时需要换行
以函数声明为例,推荐的换行方式是次行首字母与函数左括号对齐。
static const struct uk_thread *schedprio_idle_thread(struct uk_sched *s,
unsigned int proc_id);
● 每行末尾不能有空白字符
● 只有换行会严重影响代码可读性时,才允许单行超过80个字符。例如banner打印等场景
空格
● C语言关键字(if、switch、case、for、do、while、return、void等)后需要添加空格
● 逗号如果不在行尾,后面需要添加空格
● 不要在圆括号周围添加空格
if ( condition ) {
}
if (condition) {
}
● 对于指针类型定义,'*'靠近变量名、函数名
char* name;
char *name;
char *func(int *arg);
花括号
● 对于function,将花括号(“{”、“}”)放置在下一行首
void function(int arg)
{
}
● 除function外,将左花括号(“{”)放置在当前代码行,右花括号(“}”)另起一行。右花括号后可跟随条件语句。
if (x == y) {
} else if (x > y) {
} else {
}
do {
body of do-loop
} while (condition);
● 为降低长线维护发生逻辑错误的概率,对于条件判断等逻辑,即时是单行代码也请使用大括号
if (x == y) {
x++;
}
while (condition1) {
if (condition2) {
x++;
} else {
y++;
}
}
● 为了保证代码可读性,请尽量减少花括号的嵌套层数。
if (condition1) {
if (condition2) {
}
}
if (condition1 && condition2) {
}
使用typedef的场景
● 提升跨平台兼容性
● 需要隐藏具体实现
● 通过别名可以直观地识别类型信息
typedef unsigned long int uint64_t;
typedef __u32 __lcpuid;
头文件
● 为了避免重复导入头文件,需要使用include guard宏,命名方式为__TN_{filename}H_
#ifndef __TN_SCHEDPRIO_H__
#define __TN_SCHEDPRIO_H__
#endif
● 尽量避免C代码和汇编代码引用相同头文件。如果不得不这么做,使用__ASSEMBLY__进行区分
#if !__ASSEMBLY__
#endif
#if __ASSEMBLY__
#endif
注释
● 采用多行注释风格
while (condition) {
...
}
while (condition) {
...
}
● 使用Doxgen风格的函数注释,注释中行首缩进使用空格
struct timer *timer_create(
systick_t init_tick,
void (*timeout_func)(void *parameter),
void *parameter,
unsigned long flag);
预处理指令注释
● 当#ifdef、#else、#endif等条件预处理指令跨越很长的代码段时,往往可读性很差。需要在分支结束处通过注释进行条件说明,注释内容为前一个分支处理的条件。
#ifdef CONFIG_HAVE_SMP
#else
#endif
● 对于#if、#ifdef、#elif等预处理指令,由于关键字后就是判断条件,不需要添加注释
● 预处理指令跨度较短,可以直观理解代码逻辑时,不需要添加注释
命名
● 全局变量、全局可见函数命名需要满足自描述性,不要使用不可识别的缩写
struct thread curthr;
struct thread *curthr();
struct thread current_thread;
struct thread *current_thread();
● 采用蛇形命名,多个单词使用下划线(‘_’)连接
void some_function(void);
int some_var;
#define SOME_MACRO 0
宏定义
● 采用全小写字母命名函数(形式的宏),采用全大写字母命名常量
● 用于操作寄存器的函数形式的宏,可以采用全大写字母命名
● 如果函数形式的宏包含未使用的参数,请使用static inline函数,不要使用宏
● 多行语句需要使用do…while
#define macrofun(a, b, c)\
do {\
if ((a) == 5)\
do_this((b), (c));\
} while (0)
● 不要在宏中使用return,这会导致调用该宏的函数返回
● 使用表达式定义常量时,必须用括号括起来,避免在使用时由于操作符优先级导致的异常结果;同样,对于函数形式的宏,每个参数在函数体中都要用括号括起来
#define SOME_CONSTANT 0x80000000
#define ANOTHER_CONSTANT (0xFF | SOME_CONSTANT)
#define BASE_ADDR 0x8000
#define SOME_REGISTER(x) (BASE_ADDR + (x))
● 宏中定义临时变量时,要考虑作用域。使用常见的临时变量名,在宏展开时可能与同作用域的其他变量冲突
#define some_function()\
do {
int ret;
(ret);
} while (0)
#define some_function()\
do {
int _some_function_ret;
(_some_function_ret);
} while (0)
函数实现
● 尽量保持函数体短小精炼,一个函数实现单一功能
● 复杂度较高的函数尽量拆分成多个子函数实现,以提升可读性和可维护性
● 如果函数中使用的临时变量超过10个,它的功能可能过于复杂了,需要考虑如何拆分
● 函数体后需要保留一行空行
void some_function(void)
{
}
● 变量声明和功能代码之间需要保留一行空行
void some_function(void)
{
int some_var_i;
char some_var_c;
if (condition1) {
some_var_i++;
}
}
● 如果一个函数需要被其他微库调用,需要将函数名写入到所在微库的exportsyms.uk文件中。例如tenon/lib/tnschedprio/exportsyms.uk
函数返回值
tenon目前没有提供bool型,当函数返回一个整型值,用于表示函数功能是否异常时,遵循以下规则:
● 操作、执行、命令类函数
○ 返回 0 值代表成功,非0 值代表错误码
● 判断类函数
○ 返回 0 值代表false,1 值代表true
int is_cpu();
int configure_gic_distriutor(void *dtb);
函数退出处理和GOTO使用
● 可以使用GOTO统一处理函数的退出逻辑(错误处理、资源回收等),但需要满足:
○ 使用GOTO可以减少条件分支,或者减少代码嵌套层数
○ 函数有多个退出点,使用GOTO将退出逻辑汇总在一处,可以减少重复代码,同时避免后续维护过程中多点修改出现遗漏
● 使用GOTO时,标签名需要有实际意义,例如说明后续代码的意图,说明走到该分支的原因等。避免使用err1、err2等无意义标签
int testfunc(void)
{
void *a, *b;
int rc = 0;
a = malloc(...);
if (unlikely(!a)) {
return -ENOMEM;
}
b = malloc(...);
if (unlikely(!b)) {
rc = -ENOMEM;
goto out_free_a;
}
...
if (condition) {
rc = 1;
goto out_free_b;
}
out_free_b:
free(b);
out_free_a:
free(a);
return rc;
}
● 其他场景请尽量避免使用GOTO
汇编
● 如果使用C代码能够实现相同功能,尽量不要使用汇编代码
● 指令和操作数之间使用Tab
● 存在多行汇编指令时,每条指令一行,"\n\t"结尾
● 使用asm volatile替代__asm__ volatile
__asm__ __volatile__ (
"instrop, op\n\t"
"instr2op, op"
:::);
asm volatile (
"instrop, op\n\t"
"instr2op, op"
:::);
● 对于较长的内联汇编代码,尽量添加足够的注释,便于开发者理解代码功能
后续继续学习其他的规范,进行分享。
原文地址:https://blog.csdn.net/qq_37286579/article/details/144738351
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!