嵌入式C语言编码规范

1、总体原则

1.1、代码以人为本

编写程序应该以人为本,计算机第二。代码首先是给人读的,好的代码应当可以像文章一样通顺易读。遵循以下原则:

  1. 不使用单词缩写、不使用汉语拼音
  2. 良好的命名规则
  3. 尽量不使用跨文件的全局变量
  4. 废弃的代码要及时清除
  5. 重复代码应该尽可能提炼成函数,避免出现过长的函数
  6. 文件职责单一化
  7. 一个函数仅完成一个功能

1、文件与目录

原则:嵌入式代码每个.c文件必须包含一个.h文件。函数的定义应在相应的.c文件中,声明在相应的.h文件中。

1.1、 对于源码文件中的段落安排

我们建议按如下的顺序排列:

  1. 文件头注释
  2. 防止重复引用头文件的设置
  3. #include 部分
  4. #define 部分
  5. enum 常量声明
  6. 类型声明和定义,包括 struct、union、typedef 等
  7. 全局变量声明
  8. 文件级变量声明
  9. 全局或文件级函数声明
  10. 函数实现。按函数声明的顺序排列
  11. 文件尾注释

1.2、在引用头文件时,使用 <> 来引用预定义或者特定目录的头文件,使用 “” 来引用当前目录或者路径相对于当前目录的头文件。

#include <stdio.h> /* 标准头文件 */
#include <projdefs.h> /* 工程指定目录头文件 */
#include “global.h” /* 当前目录头文件 */
#include “inc/config.h” /* 路径相对于当前目录的头文件 */

1.3、 为了防止头文件被重复引用,应当用 ifndef/define/endif 结构产生预处理块。

#ifndef __DISP_H /* 文件名前名加两个下划线“__”,后面加 “_H”*/
#define __DISP_H

//用户代码

#endif

1.4、头文件中只存放“声明”而不存放“定义”,通过这种方式可以避免重复定义。

/* 模块 1 头文件: module1.h */
extern uint8_t g_ucPara; /* 在模块 1 的 .h 文件中声明变量 */
/* 模块 1 实现文件:module1.c */
uint8_t g_ucPara = 5; /* 在模块 1 的 .c 文件中定义全局变量 g_ucPara */

2、代码注释

2.1、总体注释要求

  1. 注释语言必须准确、易懂、简洁;
  2. 修改代码同时修改相应的注释, 以保证注释与代码的一致性,不再有用的注释要删除;
  3. 建议多使用中文,除非能用非常流利准确的英文表达。
  4. 采用中文注释时采用GB2312编码方式进行编码。
  5. 优秀的代码可以自我解释,不通过注释即可轻易读懂。
  6. 注释应与其描述的代码靠近,对代码的注释应放在其上方或右方(对单条语句的注释)相邻位置,不可放在下面,如放于上方则需与其上面的代码用空行隔开。
  7. 注释与所描述内容进行同样的缩排。

2.2、源文件头部的注释


/*==========================================================================================================================
//  Copyright @ 公司名称,2018-2020,项目
//  @文件名称: (文件名)
//  @文件说明: (用于详细说明此程序文件完成的主要功能,与其他模块或函数的接口,输出值、取值范围、含义及参数间的控制、顺序、独立或依赖等关系)
//--------------------------------------------------------------------------------------------------------------------------
//  @硬件平台: 芯片型号
//  @软件平台: 软件型号
//--------------------------------------------------------------------------------------------------------------------------
//  版本号		日期	        作者	        说明
============================================================================================================================*/

2.3、函数头部的注释


/*==========================================================================================================================
//  @函数名称:
//  @函数描述:
//--------------------------------------------------------------------------------------------------------------------------
//  @参数值:
//		输入参数:
//		输出参数:
//  @返回值:
============================================================================================================================*/

2.4、块注释

开头: /*
结尾: */
例:

/*
* ... This is a block comment ...
*/

2.5 行注释
开头: //
例:

// This is a line comment...

3、命名规则

3.1、总体命名要求

  1. 所有命名都应使用标准的英文单词或缩写,最好不使用拼音或拼音缩写,除非该名字描述的是中文特有的内容,如半角、全角, 声母、韵母等。
  2. 所有命名都应遵循达意原则,即名称应含义清晰、明确。
  3. 所有命名都应该完整的反应具体的功能。
  4. 所有命名都应尽量使用全称。

3.2、文件命名规则

  1. 用户编写的文件命名统一采用小写字符+下划线的方式。
    实例:task_app_diagnostic.c task_app_diagnostic.h
  2. 文件名要与模块名对应。

3.3、函数命名规则

3.3.1、普通函数

  1. 函数命名应以函数要执行的动作命名,一般采用动词或者动词+名词的结构
  2. 函数命名使用驼峰命名法,一个文件的内部使用static关键字限制函数作用域。
//文件内部函数
static int16_t Service0x10Process(uint8_t *udsData, uint16_t udsLen, uint8_t functionAddressFlag)
//文件外部函数
void TaskEcuDiagnostic(void *pvParameters)
  1. 函数参数尽量保持顺序从左到右为:输入、修改、输出。

3.3.2、指针函数

  1. 采用*p+驼峰命名法
typedef int16_t (*pServiceFunction)(uint8_t *udsData, uint16_t udsLen, uint8_t functionAddressFlag);

3.4、宏命名规则

  1. 宏定义全部使用大写,两个单词之间用下划线隔开。
  2. 除了头文件或编译开关等特殊标识定义,宏定义不能使用下划线“_”开头和结尾
  3. 用宏定义表达式时,要使用完备的括号
  4. 将宏定义的多条表达式放在大括号中,更好的方法是多条语句写成do while(0)的方式。
  5. 使用宏时,不允许参数发生变化
  6. 尽量使用函数代替宏表达式
  7. 常量建议使用const定义代替宏

3.5、变量类型

尽量使用全称等

typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
typedef signed char int8_t;
typedef signed short int16_t;
typedef signed int int32_t;
#define __IO volatile

3.6、变量命名

  1. 局部变量采用小驼峰命名法,即第一个单词小写,第二个单词首字母大写
uint8_t negativeNum = 0;
  1. 跨文件的全局变量在小驼峰命名法加前缀’g_’
uint8_t g_negativeNum = 0;
  1. 本文件的全局变量在小驼峰命名法加前缀’m_’
uint8_t m_negativeNum = 0;
  1. 静态变量在小驼峰命名法增加“s_”前缀。
static uint8_t sNegativeNum = 0;
  1. 指针变量加“p_”
  2. 除了通用的缩写以外,不得使用单词缩写,不得使用汉语拼音

3.7、类型命名

3.7.1、结构体类型

  1. 采用str_+大驼峰式命名法_TypeDef,成员变量采用小驼峰命名法
typedef struct  
{
    unsigned char studentName;
    unsigned char  studentAge;
    ......

}str_StudentTypeDef,*str_pStudentTypeDef;

str_StudentTypeDef str_Student;

3.7.2、枚举类型

  1. 采用enum_+大驼峰式命名法_TypeDef,成员变量采用小驼峰命名法
typedef enum  
{
    securityTimerNone,
    securityTimerResetDelay,
    ......

}enum_SecurityTimerTypeDef;

enum_SecurityTimerTypeDef m_securityTimer;

4、排版布局

4.1、头文件排版布局

头文件排版内容依次为包含的头文件、宏定义、类型定义、声明变量、声明函数。且各个种类的内容间空三行。

  • 5
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

redeemer奇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值