分支语句 
为每个case语句添加单个缩进 
 
使用额外的单缩进break语句在每个case或default 
 
/* OK, every case has single indent */ 
/* OK, every break has additional indent */ 
switch (check()) { 
    case 0: 
        do_a(); 
        break; 
    case 1: 
        do_b(); 
        break; 
    default: 
        break; 
} 
 
/* Wrong, case indent missing */ 
switch (check()) { 
case 0: 
    do_a(); 
    break; 
case 1: 
    do_b(); 
    break; 
default: 
    break; 
} 
 
/* Wrong */ 
switch (check()) { 
    case 0: 
        do_a(); 
    break;      /* Wrong, break must have indent as it is under case */ 
    case 1: 
    do_b();     /* Wrong, indent under case is missing */ 
    break; 
    default: 
        break; 
} 
总是包含default语句 
/* OK */ 
switch (var) { 
    case 0: 
        do_job(); 
        break; 
    default: break; 
} 
 
/* Wrong, default is missing */ 
switch (var) { 
    case 0: 
        do_job(); 
        break; 
} 
如果需要局部变量,则使用花括号并在里面放入break语句。将左花括号放在case语句的同一行 
switch (a) { 
    /* OK */ 
    case 0: { 
        int32_t a, b; 
        char c; 
        a = 5; 
        /* ... */ 
        break; 
    } 
 
    /* Wrong */ 
    case 1: 
    { 
        int32_t a; 
        break; 
    } 
 
    /* Wrong, break shall be inside */ 
    case 2: { 
        int32_t a; 
    } 
    break; 
} 
宏和预处理指令 
总是使用宏而不是文字常量,特别是对于数字 
所有的宏必须是全大写的,并带有下划线_字符(可选),除非它们被明确标记为function,将来可能会被常规函数语法替换 
/* OK */ 
#define MY_MACRO(x)         ((x) * (x)) 
 
/* Wrong */ 
#define square(x)           ((x) * (x)) 
总是用圆括号保护输入参数 
/* OK */ 
#define MIN(x, y)           ((x) < (y) ? (x) : (y)) 
 
/* Wrong */ 
#define MIN(x, y)           x < y ? x : y 
总是用括号保护最终的宏计算 
/* Wrong */ 
#define MIN(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)语句保护它 
typedef struct { 
    int32_t px, py; 
} point_t; 
point_t p;                  /* Define new point */ 
 
/* Wrong implementation */ 
 
/* Define macro to set point */ 
#define SET_POINT(p, x, y)  (p)->px = (x); (p)->py = (y)    /* 2 statements. Last one should not implement semicolon */ 
 
SET_POINT(&p, 3, 4);        /* Set point to position 3, 4. This evaluates to... */ 
(&p)->px = (3); (&p)->py = (4); /* ... to this. In this example this is not a problem. */ 
 
/* Consider this ugly code, however it is valid by C standard (not recommended) */ 
if (a)                      /* If a is true */ 
    if (b)                  /* If b is true */ 
        SET_POINT(&p, 3, 4);/* Set point to x = 3, y = 4 */ 
    else 
        SET_POINT(&p, 5, 6);/* Set point to x = 5, y = 6 */ 
 
/* Evaluates to code below. Do you see the problem? */ 
if (a) 
    if (b) 
        (&p)->px = (3); (&p)->py = (4); 
    else 
        (&p)->px = (5); (&p)->py = (6); 
 
/* Or if we rewrite it a little */ 
if (a) 
    if (b) 
        (&p)->px = (3); 
        (&p)->py = (4); 
    else 
        (&p)->px = (5); 
        (&p)->py = (6); 
 
/* 
 * Ask yourself a question: To which `if` statement `else` keyword belongs? 
 * 
 * Based on first part of code, answer is straight-forward. To inner `if` statement when we check `b` condition 
 * Actual answer: Compilation error as `else` belongs nowhere 
 */ 
 
/* Better and correct implementation of macro */ 
#define SET_POINT(p, x, y)  do { (p)->px = (x); (p)->py = (y); } while (0)    /* 2 statements. No semicolon after while loop */ 
/* Or even better */ 
#define SET_POINT(p, x, y)  do {    \   /* Backslash indicates statement continues in new line */ 
    (p)->px = (x);                  \ 
    (p)->py = (y);                  \ 
} while (0)                             /* 2 statements. No semicolon after while loop */ 
 
/* Now original code evaluates to */ 
if (a) 
    if (b) 
        do { (&p)->px = (3); (&p)->py = (4); } while (0); 
    else 
        do { (&p)->px = (5); (&p)->py = (6); } while (0); 
 
/* Every part of `if` or `else` contains only `1` inner statement (do-while), hence this is valid evaluation */ 
 
/* To make code perfect, use brackets for every if-ifelse-else statements */ 
if (a) {                    /* If a is true */ 
    if (b) {                /* If b is true */ 
        SET_POINT(&p, 3, 4);/* Set point to x = 3, y = 4 */ 
    } else { 
        SET_POINT(&p, 5, 6);/* Set point to x = 5, y = 6 */ 
    } 
} 
不缩进子语句内#if语句 
/* OK */ 
#if defined(XYZ) 
#if defined(ABC) 
/* do when ABC defined */ 
#endif /* defined(ABC) */ 
#else /* defined(XYZ) */ 
/* Do when XYZ not defined */ 
#endif /* !defined(XYZ) */ 
 
/* Wrong */ 
#if defined(XYZ) 
    #if defined(ABC) 
        /* do when ABC defined */ 
    #endif /* defined(ABC) */ 
#else /* defined(XYZ) */ 
    /* Do when XYZ not defined */ 
#endif /* !defined(XYZ) */ 
文档 
文档化的代码允许doxygen解析和通用的html/pdf/latex输出,因此正确地执行是非常重要的。 
 
对变量、函数和结构/枚举使用doxygen支持的文档样式 
经常使用\作为doxygen,不要使用@ 
始终使用5x4空格(5个制表符)作为文本行开始的偏移量 
/** 
 * \brief           Holds pointer to first entry in linked list 
 *                  Beginning of this text is 5 tabs (20 spaces) from beginning of line 
 */ 
static 
type_t* list; 
每个结构/枚举成员都必须包含文档 
注释的开头使用12x4空格偏移量 
/** 
 * \brief           This is point struct 
 * \note            This structure is used to calculate all point 
 *                      related stuff 
 */ 
typedef struct { 
    int32_t x;                                  /*!< 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 
 
在参数名和描述之间使用冒号: 
 
/** 
 * \brief           Sum `2` numbers 
 * \param[in]       a: First number 
 * \param[in]       b: Second number 
 * \return          Sum of input values 
 */ 
int32_t 
sum(int32_t a, int32_t b) { 
    return a + b; 
} 
 
/** 
 * \brief           Sum `2` numbers and write it to pointer 
 * \note            This function does not return value, it stores it to pointer instead 
 * \param[in]       a: First number 
 * \param[in]       b: Second number 
 * \param[out]      result: Output variable used to save result 
 */ 
void 
void_sum(int32_t a, int32_t b, int32_t* result) { 
    *result = a + b; 
} 
如果函数返回枚举的成员,则使用ref关键字指定哪个成员 
/** 
 * \brief           My enumeration 
 */ 
typedef enum { 
    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_t 
check_value(void) { 
    return MY_OK; 
} 
对常量或数字使用符号(' NULL ' => NULL) 
/** 
 * \brief           Get data from input array 
 * \param[in]       in: Input data 
 * \return          Pointer to output data on success, `NULL` otherwise 
 */ 
const void * 
get_data(const void* in) { 
    return in; 
} 
宏的文档必须包括hideinitializer doxygen命令 
/** 
 * \brief           Get minimal value between `x` and `y` 
 * \param[in]       x: First value 
 * \param[in]       y: Second value 
 * \return          Minimal value between `x` and `y` 
 * \hideinitializer 
 */ 
#define MIN(x, y)       ((x) < (y) ? (x) : (y)) 
头/源文件 
在文件末尾留下一个空行 
 
每个文件都必须包括文件的doxygen注释和后跟空行的简要描述(使用doxygen时) 
 
/** 
 * \file            template.h 
 * \brief           Template include file 
 */ 
                    /* Here is empty line */ 
每个文件(头文件或源文件)必须包含许可证(开始注释包括单个星号,因为doxygen必须忽略这个) 
 
使用与项目/库已经使用的相同的许可证 
 
/** 
 * \file            template.h 
 * \brief           Template include file 
 */ 
 
/* 
 * Copyright (c) year FirstName LASTNAME 
 * 
 * Permission is hereby granted, free of charge, to any person 
 * obtaining a copy of this software and associated documentation 
 * files (the "Software"), to deal in the Software without restriction, 
 * including without limitation the rights to use, copy, modify, merge, 
 * publish, distribute, sublicense, and/or sell copies of the Software, 
 * and to permit persons to whom the Software is furnished to do so, 
 * subject to the following conditions: 
 * 
 * The above copyright notice and this permission notice shall be 
 * included in all copies or substantial portions of the Software. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE 
 * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 
 * OTHER DEALINGS IN THE SOFTWARE. 
 * 
 * This file is part of library_name. 
 * 
 * Author:          FirstName LASTNAME <optional_email@example.com> 
 */ 
头文件必须包含保护符#ifndef 
 
头文件必须包含c++检查 
 
在c++检查之外包含外部头文件 
 
首先用STL C文件包含外部头文件,然后是应用程序自定义文件 
 
头文件必须包含其他所有头文件,以便正确编译,但不能包含更多头文件(如果需要,.c应该包含其余的头文件) 
 
头文件必须只公开模块公共变量/类型/函数 
 
在头文件中使用extern作为全局模块变量,稍后在源文件中定义它们 
 
/* file.h ... */ 
#ifndef ... 
 
extern int32_t my_variable; /* This is global variable declaration in header */ 
 
#endif 
 
/* file.c ... */ 
int32_t my_variable;        /* Actually defined in source */ 
不要把.c文件包含在另一个.c文件中 
 
.c文件应该首先包含相应的.h文件,然后是其他文件,除非另有明确的必要 
 
在头文件中不包含模块私有声明 
 
头文件示例(示例中没有license) 
 
/* License comes here */ 
#ifndef TEMPLATE_HDR_H 
#define TEMPLATE_HDR_H 
 
/* Include headers */ 
 
#ifdef __cplusplus 
extern "C" { 
#endif /* __cplusplus */ 
 
/* File content here */ 
 
#ifdef __cplusplus 
} 
#endif /* __cplusplus */ 
 
#endif /* TEMPLATE_HDR_H */ 
 |