EMBEDDED C CODING STANDARD

DESIGN(E) 314/414

February 2011

原文在此

yafc18@gmail.com 闲着蛋疼翻译,请指正

花括弧{}

  • 花括弧应该紧随 if, else, switch, while, do, for 语句,包围代码块。即使是一单句或者空语句也应使用
  • 左括弧应在代码块首,右括弧应在代码块末,且与左括弧保持相同缩进

例:

if ((a < b) && (b < c))
{
    result = (3 * a) + b;
}
return result;

括号()

不要信赖运算优先级,多使用括号

应限制的关键词

不要使用 gotocontinue 。除非是在 switch 词句中,也不要使用 break
continue 和 break 也不用,难度有点高呐

应鼓励的关键词

一定要用 volatile 修饰中断函数会使用的全局变量

注释

  • 注释不要嵌套
  • 不要用 /*...*/ 禁用代码,使用条件编译 #if (0) ... #endif
  • 注释位于代码块前,并保持相同的缩进。并在代码块后留一空行
  • 不要解释作用显而易见的代码

空格

  • if, else, while, for, switch, return 后空一格
  • 赋值操作符 =, +=, -=, *=, /=, %=, &=, |=, ^=, ~=, != 前后均空一格
  • 二元操作符 +, -, *, /, %, <, <=, >, >=, ==, !=, <<, >>, &, &&, || 前后均空一格
  • 一元操作符 +, -, ++, --, !, ~ 应紧贴操作数,并在另一端空一格
  • 指针操作符号 *, & 在声明(定义呢?)时前后均空一格。而使用时,紧贴操作数,并在另一端空一格
  • 数组索引时 [, ] 和其包围内容间无空格
  • 括号内的表达式应紧贴左右括号
  • 函数使用时左右括号应紧贴参数,而在声明时函数名与左括号应空一格
  • 逗号后紧随一空格
  • for 语句中的分号后紧随一空格
  • 语句结束处紧随分号,而不应留空。

空行

  • 一条语句占用一行
  • 自然代码段前后均应空一行,比如循环语句,if-elseswitch 和连续声明/定义区

缩进

  • 每级缩进3个空格 个人表示,偏好4个
  • 不要使用制表符缩进,除非编辑器支持将其自动替换成空格
  • switch 语句内部, case 应缩进一级,同时其下内容再缩进一级
  • 语句过长超出一行时,其后内容应缩进至适合阅读处
  • 使用等宽字体

例:

sys_error_handler(int error)
{
    switch (err)
    {
        case ERR_ONE:
            ………;
            ………;
            break;
        default:
            ………;
            ………;
            break;
    }
    if ((very_long_comparison_here
                && second very_long_comparison_here)
            || third very_very_long_comparison_here)
    {
        ………;
        ………;
    }
}

制表符

不要使用它

模块

  • 模块名应由小写字母,数字和下划线组成
  • 模块名间保证前8个字符惟一
  • 模块名中不要包含标准库名,如 stdio 或者 math
  • 含有 main 函数的模块名中应含有 main 字样

头文件

  • 每个源文件应有对应的头文件
  • 头文件应该只含有对外服务的函数声明,常数和数据结构
  • 不要在头文件中定义变量,使用声明
  • 不要在头文件中使用 #include

源文件

  • 源文件结构:
    说明,#include语句,数据结构和常量声明,静态数据定义,私有函数声明,公共函数体,私有函数体
  • 源文件应包含对应的头文件
  • 不要引用未使用的头文件
  • 不要引用其它源文件

函数

  • 程序名不要包含限定词,如: interrupt, inline, true
  • 程序名不要使用大写字母
  • 程序名使用下划线连接单词
  • 程序名用于描述其作用:使用"名词-动词"结构(如adc_read()),或者问答方式(如input_is_high()
  • 公开函数应带有模块的前缀, 如 display_lcd_init(), display_led_is_on()
  • 函数体代码长度应限制在100行内
  • 函数应只在结尾处有惟一出口,就是说,return只出现一次 表示很难呢
  • 参数名要表示清楚其意义

变量与常量

  • 变量名不要包含限定词
  • 变量名不要使用大写字母
  • 变量名使用下划线连接单词
  • 变量名用于描述其作用
  • 全局变量使用字母 g 前缀,如: g_zero_offset
  • 指针使用字母 p 前缀,如: *p_led_reg
  • 布尔值使用字母 b 前缀,如某个全局布尔变量: gb_is_buffer_full
  • 使用 #define 代替神奇数字(magic number),常量用大写。多个源文件要使用时,包含在头文件中

例:

#define MAX_LOOPS 10 int loop;
for (loop = 0; loop < MAX_LOOPS; loop++)
{
    ……;
}

变量定义

不要将指针和其它变量放在同行。如:

char * x, y; // No
char * x; // Yes
char y; // Yes

if-Else 语句

  • if-else-if 中最短子句放最前
  • if-else 嵌套不要超过两层
  • if 语句中嵌套 if-else 子句时必须用 else 结尾
  • 变量与常量比较时,常量放在左边 经典写法

例:

if (ON == power_supply) // “if (ON = power_supply)” will result in an error
    // message, but not “if (power_supply = ON)”.
{
    ……; // Placing the shorter clause here and the longer
    // clause last will make the logic easier to follow.
}
else if (OFF == power_led)
{
    ……;
}
else //similar to “default ” in a switch statement
{
    ……;
    ……;
    ……;
    ……;
}

Switch 语句

  • break 应和相应的 case 对齐
  • 必须有 default 代码块

例:

switch (err)
{
    case ERR_A:
        ………;
        break;
    case ERR_B:
        ………;
        break;
    default:
        ………;
        break;
}

循环

  • 使用常量控制深度,而非神奇数字

例:

for (int loop = 0; loop < MAX_LOOPS; loop++) //constants should be in capitals
{
    ……;
}
  • 死循环使用
    while(1);
    或者
    for(;;);

Most of the recommendations listed in this document are from: Netrino Embedded C Coding Standard

Reference

This document and the information it contains is Copyright © 2009 Netrino, LLC (www.netrino.com). It is allowable for individuals, companies and institutions to adopt all or some of the coding rules herein, indeed we hope many will, This may be done simply by identifying the Netrino Embedded C Coding Standard, and retaining this paragraph in its entirety. All other rights are reserved by Netrino, LLC.