统一代码注释规范
<h2>1.总则</h2><ul>
<li><strong>目的</strong>:提高代码的可读性和便于维护。</li>
<li><strong>清晰</strong>:注释应简洁明了,避免歧义,描述代码的目的、方法和背景信息;注释内容应聚焦于帮助理解代码。</li>
<li><strong>准确</strong>:确保注释和代码逻辑一致。</li>
<li><strong>适度</strong>:避免无意义的注释,必要时注释,不要过度。</li>
</ul>
<p><img src="https://www.3bbs.cn/index-diy/img.php?url=https://mmbiz.qpic.cn/sz_mmbiz_png/LhYwUvIicQJibOTriaKia9YI2h3c8ictKf5Hrr9kuGHjDLrk8HlKhJYmlYAialWQmzMgRI6eYtTZsaABhYIaVu1NcianA/640?wx_fmt=png&from=appmsg&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片" /></p>
<h2>2.注释类型</h2>
<h3>2.1.文件注释</h3>
<h5>要求</h5>
<ul>
<li>每个源文件和头文件必须包含文件头注释,描述文件的功能、作者、日期和版本信息。</li>
</ul>
<h5>格式</h5>
<pre><code>/**
* @file ring_queue.h
* @brief 环形队列缓存区
* @author Eureka (eureka@mail.com)
* @version 1.0
* @date 2025-01-22
*
* @par 修改日志:
* <table>
* <tr><th>Date <th>Version <th>Author<th>Description
* <tr><td>2025-01-22 <td>1.0 <td>Eureka <td>首次创建
* </table>
*
* @copyright Copyright (c) 2025Eureka
*/
</code></pre>
<h3>2.2.函数注释</h3>
<h5>说明</h5>
<p>标准规范下,应该需要在源文件中对函数进行注释,在头文件中不对函数进行注释(参考各个大厂MCU的HAL源码库可以看出)。这样做的好处是头文件中很简洁,可以快速查到到所需的API。</p>
<p>但在模块化的设计中,常常以库和头文件的形式提供模块,这种情况下,如果只在源码中注释了,被封装成库后,就无法看到注释的内容,鉴于此,内部约定规范要求如下:</p>
<h5>要求</h5>
<ul>
<li>如果是没有对外释放需要的代码,统一在源文件中进行注释,头文件中无需注释,只保留一份注释</li>
<li>标准化部门,统一对头文件中暴露的函数进行注释,所有非内联函数都应有函数头注释,说明其功能、参数和返回值</li>
</ul>
<h5>格式</h5>
<pre><code>/**
* @brief 向其他主机发送数据
* @param host 主机节点
* @param ta 目标主机
* @param data 数据内容
* @param len 数据长度
* @return >=0::发送成功 其他:失败 参考 @ref TErrorCode
*/
EXP_API int SonHostSend(int host, uint16_t ta, const uint8_t *data, int len);
</code></pre>
<h3>2.3.代码块注释</h3>
<h5>要求</h5>
<ul>
<li>复杂的代码块应在逻辑前添加注释,描述<strong>整体目的</strong>或<strong>关键步骤</strong>。</li>
<li>不推荐大篇幅的说明,对函数特殊的设计应该在设计文档中描述,而不是在代码中</li>
<li>如果实在注释内容较长,则进行多行注释,否则使用单行注释</li>
</ul>
<h5>示例</h5>
<pre><code>int example(void)
{
===================================
// 写入非 _this->EscFlag 转义符
while (pos < end && *pos != _this->EscFlag)
pos++;
// 检查尺寸是否溢出
size = pos - begin;
if (size > _this->Rx.End - _this->Rx.Pos)
{
_this->RxLostBytes += _this->Rx.Total + size;
L_TransInvalid(&_this->Rx);
}
else
{
// 拷贝数据
if (size > 0)
{
memcpy(_this->Rx.Pos, begin, size);
_this->Rx.BCC = _this->DoBcc(begin, size, _this->Rx.BCC);
_this->Rx.Pos += size;
_this->Rx.Total += size;
}
===================================
}
</code></pre>
<h3>2.4.代码行注释</h3>
<h5>说明</h5>
<p>对代码中特殊操作或关键语句进行解释,尽量简洁。</p>
<h5>示例</h5>
<pre><code>result = get_gpio_level(0); ///< 0为引脚值,参考mproc_gpi_board.c GPI_DRV_CHN_ACC
</code></pre>
<h3>2.5.构造数据注释</h3>
<h5>说明</h5>
<p>这里的构造数据是指在嵌入式C中常常定义的枚举和结构体以及函数指针等。</p>
<h5>要求</h5>
<ul>
<li>头文件中的结构体和枚举,必须对头和每个成员进行注释</li>
<li>函数指针参考函数注释方法进行注释</li>
</ul>
<h5>示例</h5>
<ul>
<li>枚举</li>
</ul>
<pre><code>/**
* @brief 事件类型定义
*/
typedef enum TSonEventType
{
kEventOnConnect = 0, ///< 连接到网络
kEventOnDisConnect = 1, ///< 网络断开
kEventOnBusFault = 2, ///< 网络故障
kEventOnPageAck = 3, ///< 寻呼应答
kEventOnReceive = 4, ///< 接收到数据
kEventOnAckTimeout = 5, ///< 应答超时
}TEventType;
</code></pre>
<ul>
<li>结构体</li>
</ul>
<pre><code>/**
* @brief TBOX配置数据
*/
typedef struct TTboxConfigType
{
char *ota_cert; ///< OTA服务器根证书
char *dl_cert; ///< 下载服务器根证书
char *tbox_cert; ///< TBOX证书
char *tbox_key; ///< TBOX私钥
char *vin; ///< VIN
char *tbox_part_no; ///< TBOX 零部件号
}TTboxConfig;
</code></pre>
<ul>
<li>函数指针</li>
</ul>
<pre><code>/**
* @brief 消息接收回调函数指针
* @param owner 用户参数指针
* @param sa 数据源地址
* @param len 数据长度
* @param data 数据指针
*/
typedef void (*TOnReceive)(void *owner, uint16_t sa, int len, const uint8_t *data);
</code></pre>
<h2>3.注释格式</h2>
<h3>3.1.注释语法</h3>
<h5>说明</h5>
<p>为了满足 <code>API</code> 导出说明文档(使用 <code>doxgen</code> 工具导出)的需要,注释参数需要严格满足 <code>doxgen</code> 语法的需要</p>
<h5>单行注释</h5>
<ul>
<li>注释行:指注释单独占用一行,在 <code>C/C++</code> 中,单行使用 <code>*</code> 进行注释</li>
<li>行内注释:指在代码行的行尾进行注释,要求行尾注释使用 <code>*/<</code> 进行注释</li>
</ul>
<h5>多行注释</h5>
<ul>
<li>多行注释参考 <code>C/C++</code>注释语法,使用</li>
</ul>
<pre><code>/*
* 注释内容1
* 注释内容2
* ...
*/
</code></pre>
<h5>文件头</h5>
<ul>
<li>使用多行注释</li>
<li><code>@file</code> 后面紧跟此文件的名称</li>
<li><code>@brief</code> 简述此文件的内容</li>
<li><code>@author</code> 此文件的第一作者</li>
<li><code>@version</code> 此文件当前的版本</li>
<li><code>@date</code> 此文件的最后一次修改时间</li>
<li><code>@par</code> 用于说明修改日志</li>
<li><code>@copyright</code> 权利约束说明</li>
</ul>
<h5>函数头</h5>
<ul>
<li><code>@brief</code> 说明此函数的作用</li>
<li><code>@param</code> 说明此函数的参数</li>
<li><code>@return</code> 说明返回值(如果无返回,则不需要此字段)</li>
</ul>
<h5>块注释</h5>
<p>用于注释结构体、枚举、代码块等。</p>
<pre><code>/**
* @brief 概述此块内容
*/
</code></pre>
<h3>3.2.语言规范</h3>
<h5>要求</h5>
<ul>
<li>编码:统一使用 <code>UTF8</code></li>
<li>统一使用要求的语言(中文)注释,不允许两种及以上的语言混合注释</li>
<li>避免主观词汇,例如“也许”“可能”</li>
<li>禁止长篇大论</li>
<li>自己不清楚的不要注释,例如:张三说这个地方需要加一,否则功能会异常</li>
<li>一两句描述不清楚的,将详细的描述写入设计文档,在代码中加入说明引用来源,比如:<code>// 参考 《sonhost设计文档-V1.2.0.6.pdf》3.6.2</code></li>
</ul>
<h3>3.3.对齐缩进</h3>
<h5>要求</h5>
<ul>
<li>注释应对齐关键代码或结构体成员,保持视觉美观。</li>
</ul>
<h2>4.注释误区</h2>
<ul>
<li>不必要的注释</li>
<li>过于冗长的注释</li>
<li>注释不清晰,导致“反向注释”</li>
</ul>
<h2>5.快捷工具</h2>
<p>在vscode编辑器中,可以使用插件实现规范注释,如“Doxgen”插件,用于生成doxgen的语法参数,“Snippet”用于快捷插入注释。</p>
页:
[1]