C语言编写规范


title: ‘C语言编写规范’
date: 2023-10-18 11:31:12
tags: [嵌入式,C语言,规范]

起:2023年10月18日11:45:46
版本信息:
V1.00 初版 2023年10月20日11:13:36

V1.01:新增注释规则 2023年10月21日14:51:57

前言

实话实说,我目前这一点,做的不是很好,经常随心所欲的命名函数和中间变量。
因此,借着这次总结,好好规范一下自己。

一、文件规范

1.1 C文件规范

一个c文件,只对一个驱动或者一个功能,不做混用。并且,底层和应用层一定要分开。
例如,SPI驱动的OLED屏幕。SPI驱动封装为一个c文件,OLED的应用驱动封装为一个C文件,这样可以保证移植的灵活性,底层改变,但是函数接口没有变化,我就只需要改变底层驱动函数内部,和OLED驱动文件没有关系。
或者OLED驱动需要新增一个具体功能,只需要新增就好,不会改动到SPI。

特别是:因为SPI驱动可以驱动很多设备,可以在很多项目上使用,可以直接把SPI的驱动文件移植到新项目上,不需要去删除OLED 屏幕驱动的部分。

另外:确实也有看见把应用部分和底层驱动封装在同一个C文件内的,目前是遇到过一次,是墨水屏驱动,因为使用的是模拟的SPI通讯,所以就封装在同一个文件内,方便使用者直接改引脚,去做模拟通讯,省去了驱动部分的移植。

1.2 H文件规范

1.2.1 H文件结构

H文件的结构说明如下:

  • 文件说明注释,作者信息
  • #ifndef _xxx_H
  • #define _xxx_H
  • 引用相对应/需要的头文件
  • #define 变量
  • 枚举 enum
  • 结构体
  • 变量/全局变量声明
  • 函数声明【static】
  • 函数声明【extern】
  • #endif

1.2.2 函数声明规范

函数声明分为static 修饰和extern修饰。
如果只是当前的C文件使用,不对外,那用static修饰。
如果会在外部其他C文件内使用,或者main函数使用,需要使用extern修饰。

1.2.3 头文件引用规范

有两种方式:
- 第一种:每个文件只引用需要的文件
- 第二种:用一个include头文件包含项目中使用的所有头文件,其他C文件全部引用include

两种其实都可以,主要是使用场景不同。每个只引用需要的文件,移植以及排查问题,能比较方便。
通过一个文件来管理,适合项目框架比较稳定的情况下,每一次只是改IO,应用层,不需要改动到结构,那么头文件也是不需要改变的,加了新外设驱动,也只是在include中添加引用。

目前我是第二种用的比较多些。这样造成的问题是,单独的驱动移植的时候,需要判断一下需要的头文件是什么。除非是直接在项目工程上,直接去改成新项目,移除不需要的驱动,添加新驱动。

二、函数规范

2.1 函数说明注释规范

函数需要有一个函数说明,维护好的话,可以不看具体内容或者看函数名称,就能明白这个函数的主要功能是什么,输入输出是什么。提高代码的阅读效率。

我目前使用是一个小脚本,在keil中使用之后,会自动生成函数说明部分,然后按照需求,自己修改内容。默认生成的效果如下,函数名称会自己改变,作者信息可以通过改变模板文件来实现,其实整个模板都是可以改变的,只是我没有这个需求,我觉得这样目前就能满足自己的需求。

/**
  ************************************************************************** 
  ** -------------------------------------------------------------------- **
  ** @name          : EXTI9_5_IRQHandler
  ** @brief         : None
  ** @param         : None
  ** @retval        : None
  ** @author        : ZCC
  ** -------------------------------------------------------------------- **
  ** @attention     : None
  ** -------------------------------------------------------------------- **
  ************************************************************************** 
**/

脚本信息可以在CSDN或者论坛或者B站等搜到,我就不放连接了,我也是从这些地方找到的,可以搜索 keil自动注释,或者keil脚本。很多这类的文章,包含很多的脚本,比如格式化对齐等,感谢“前人”的无私分享,我们这些“后人”,才能越用越方便。

2.2 函数名称规范

2.2.1 常用函数命名法

常用命名方法:
- 匈牙利命名法
- 骆驼命名法
- 帕斯卡命名法

具体的,可以百度一下或者论坛找找说明

简单说明:
匈牙利命名法
主要思想是在函数,变量前,加入前缀,来增加对程序的理解
具体实现:标识符以一个或者多个小写字母作为前缀,后跟首字母大写的一个或者多个单词的组合,这个单词主要指明变量的用途

骆驼命名法
混合使用大小写。
具体实现:第一个单词首字母小写,其他单词首字母大写。

例如:printEmployeePaychecks(),函数名中每一个逻辑断点都有一个大写字母来标记。

帕斯卡命名法
所有单词的首字母大写。

例如:DisplayInfo()和UserName都是采用了帕斯卡命名法。

2.2.3 我使用的规范

函数使用帕斯卡命名法,函数名称所有单词的首字母大写,命名使用最好能体现函数功能。

函数名
设备名_操作名( ),用下划线分割小写字母

 例如:Tic_Init()   Adc_Is_Busy()   Uart_Tx_Char()
 例如:Tic_Init()   Adc_IsBusy()   Uart_TxChar()  【比较规范的写法】

2.3 函数内变量规范

总的变量命名规则:函数内变量使用小写字母
- 函数内的临时变量:用temp,如果有多个且特殊的,可以按照实际的需求,编写单词。
- 函数内的静态变量:static修饰的变量,用s_xxx来命名。
- 函数内的常量:使用大写字母,声明的同时用const修饰【const int XXX = 100;//也可写成:int const XXX = 100;】

三、全局变量规范

全局变量使用规范:
- 使用g_xxx来命名 【觉得最好是 g_文件名_xxx来命名。这样直接管理到变量是哪个文件中的定义】

四、程序编写风格规范

4.1 缩进规范

首行缩进,固定为4个空格;keil中,可以调整tap键表示的空格数。
下一级嵌套函数,再缩进4个空格。

4.2 空行规范

空行规范:
- 变量定义和代码之间,空一行。
- 逻辑代码块之间,空一行,区分上下逻辑
- keil自带bug,文件的最后必须有一行,否则报错【居然一直没有修复】

五、注释规范

代码注释

    代码注释最大的用处是:今后阅读更加方便。

原因是:
- 遗忘。写完代码的三天内,记性很好,不用看源码都能说清楚代码逻辑,超过三天,那就忘了。这时候,虽然知道函数的功能,但是和其他人battle的时候,问你具体实现过程,你就容易说错或者忘记。
- 提高修改效率。根据代码块的功能做注释,可以马上定位到有异常或者需要修改的代码段。
- 后期维护效率。公司级的代码,因为项目组的不同(大公司当然不一样,中小公司,都是一个软件对几个项目),后续测试和需求,往往是延迟的,等几天之后,和你说这个功能有异常,去维护的时候,需要尽快了解之前的代码执行逻辑。
- 通过函数名,返回值,参数等注释信息,确定函数功能。
- 通过函数内的代码注释去了解代码逻辑。

六、疑惑,待解

如何保证自己写的代码质量呢?
有什么检查方法?
或者有什么思维方式?

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值