目录

本人 C 语言编程规范

前言

代码编写规范应该在建立一个工程项目之前,并且贯穿整个项目的始终,以保证代码的一致性。采用标准的代码编写惯例,可以大大简化项目的维护负担,最终达到:简洁、一致、易理解、易维护、易移植的目的,非常有利于团队成员的合作。关于本人 C 语言编程规范,以简单实用为主,不会设置过多规则。写这篇文章目的是为以后介绍我开发的一些模块,其按规范编写以保持统一风格方便大家阅读代码。

总体规范

1、规范总规则概述

)单词与单词使用下划线连接,字符使用全大写或全小写;)源文件和头文件名称使用全小写;)变量和数据结构名称使用全小写;)枚举成员、宏名称使用全大写;)数据类型名称以_t结尾,枚举类型名称以_e结尾;)指针名称以p_开头,函数指针名称以_fn结尾,回调函数名称以_cb结尾。

2、源文件命名规范
  1. 使用全小写形式,单词与单词之间使用_连接;
  2. 为了避免文件(夹)重名,一般在名称前面加入前缀标识;

示范如下:

1
2
o2o_eeprom.c
o2o_eeprom.h
3、头文件总体规范
  1. 使用统一的头部声明;
  2. 加入防重复包含的宏;
  3. 此头文件包含重映射;
  4. 一些依赖头文件包含;
  5. 加入C++的兼容语句;
  6. 参数配置;
  7. 数据类型;
  8. 操作函数;

示范如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
/**
  * @file  o2o_eeprom.h
  * @brief EEPROM存储器操作对象模块
  * COPYRIGHT (C) 2021, 一春又一春设计部
  * Change Logs:
  * Date           Author       Notes
  * 2021-05-30     o2ospring    原始版本
  */
#ifndef O2O_EEPROM_H__
#define O2O_EEPROM_H__

//########################################################################################################
#include "app_cfg.h" /////////////////////// <- 按规定[app_cfg.h]作为工程所有应用模块统一配置头文件!   ##
#ifdef __O2O_EEPROM_REMAP_H //////////////// <- 如果在[app_cfg.h]定义此宏,则启动头文件重映射功能←┐   ##
#include "o2o_eeprom_remap.h" ////////////// <- 当启动重映射,则头文件包含将映射到本行定义的头文件←┘   ##
#else //##################################################################################################

#include <stdint.h> //////////////////////// <- 使用的数据定义,如: int8_t, uint32_t 等
#ifdef O2O_EEPROM_C__
#include <string.h> //////////////////////// <- 使用的字符处理,如: strcpy(), memcpy() 等
#include "rtthread.h" ////////////////////// <- 使用RT-Thread操作系统
#include "rthw.h" ////////////////////////// <- 使用RT-Thread操作系统
#endif

#ifdef __cplusplus
extern "C" {
#endif

/********************************************************************************************************/
/*++++++++++++++++++++++++++++++++++++++++++++++ 参数配置 ++++++++++++++++++++++++++++++++++++++++++++++*/
/********************************************************************************************************/

// 模块硬件级别临界处理:
#define O2O_EEPROM_VARIAB()                      register rt_base_t level;           // 使用到的变量声明
#define O2O_EEPROM_LOCKED()                      level = rt_hw_interrupt_disable()   // [关]中断总开关
#define O2O_EEPROM_UNLOCK()                      rt_hw_interrupt_enable(level)       // [开]中断总开关

/********************************************************************************************************/
/*++++++++++++++++++++++++++++++++++++++++++++++ 数据类型 ++++++++++++++++++++++++++++++++++++++++++++++*/
/********************************************************************************************************/

typedef struct o2o_eeprom_                       //新定义的结构体数据类型以“_”结束
{
	uint8_t  chip_addr;
	uint16_t i2c_ch;

}o2o_eeprom_t;                                   //新定义的结构体数据类型以“_t”结束

/********************************************************************************************************/
/*++++++++++++++++++++++++++++++++++++++++++++++ 操作函数 ++++++++++++++++++++++++++++++++++++++++++++++*/
/********************************************************************************************************/

extern int o2o_eeprom_write(o2o_eeprom_t *pob, uint32_t addr, uint8_t *pda, uint16_t len);

#ifdef __cplusplus
	}
#endif

#endif  //#ifdef __O2O_EEPROM_REMAP_H
#endif  //#ifndef O2O_EEPROM_H__

4、源文件总体规范
  1. 头部声明;
  2. 文件包含;
  3. 模块开关;
  4. 全局变量;
  5. 函数声明;
  6. 函数实现;

示范如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
/**
  * @file  o2o_eeprom.c
  * @brief EEPROM存储器操作对象模块
  * COPYRIGHT (C) 2021, 一春又一春设计部
  * Change Logs:
  * Date           Author       Notes
  * 2021-05-30     o2ospring    原始版本
  */
#define   O2O_EEPROM_C__
#include "o2o_eeprom.h"
#if (defined(O2O_APP_EEPROM_EN) && (O2O_APP_EEPROM_EN == DEF_ENABLED))
#ifdef    O2O_EEPROM_X__   //再次调用头文件,用于增加存在交叉关系的内容!
#undef    O2O_EEPROM_H__
#include "o2o_eeprom.h"
#endif

//全局变量
uint32_t o2o_g_eeprom_flag = 0;

//函数声明
int o2o_eeprom_write(o2o_eeprom_t *pob, uint32_t addr, uint8_t *pda, uint16_t len);
int o2o_eeprom_read(o2o_eeprom_t *pob, uint32_t addr, uint8_t *pbf, uint16_t len);

/**
  * @brief  EEPROM对象写操作
  * @param  *pob            要操作的EEPROM对象
  * @param  addr            要写入的位置
  * @param  *pda            要写入的数据源
  * @param  len             要写入的数据长度
  * @return >0:操作成功
  */
int o2o_eeprom_write(o2o_eeprom_t *pob, uint32_t addr, uint8_t *pda, uint16_t len)
{
	uint8_t i, dat;

}

#endif  //#if (O2O_APP_EEPROM_EN == DEF_ENABLED)

头部规范

1、文件头格式规范
  1. 文件名称;
  2. 模块摘要;
  3. 版权声明;
  4. 修改记录;

示范如下:

1
2
3
4
5
6
7
8
/**
  * @file  o2o_eeprom.c
  * @brief EEPROM存储器操作对象模块
  * COPYRIGHT (C) 2021, 一春又一春设计部
  * Change Logs:
  * Date           Author       Notes
  * 2021-05-30     o2ospring    原始版本
  */
2、函数头格式规范
  1. 函数摘要;
  2. 入口参数;
  3. 出口参数;

示范如下:

1
2
3
4
5
6
7
8
9
/**
  * @brief  主函数
  * @param  argc            输入选项/参数的个数
  * @param  *argv[]         全部选项/参数内容
  * @return 返回参数
  */
int main(int argc, char *argv[])
{
}

代码规范

1、宏定义名称书写规范
  1. 使用全大写形式,单词与单词之间使用_连接;
  2. 为了防止与其它模块重名,建议宏名称加入前缀;
  3. 宏的每个参数都要使用()括住;
  4. 只代表数值的宏,不需要使用()作为结尾;

示范如下:

1
2
#define O2O_EEPROM_SIZE    (32UL * 1024UL)
#define O2O_MAX(a, b)      (((a) > (b)) ? (a) : (b))
2、自定义类型书写规范
  1. 使用全小写形式,单词与单词之间使用_连接;
  2. 新定义数据类型名称以_t结尾;
  3. 对于结构体名称以_结尾;

示范如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
typedef unsigned char  uint8_t;
typedef signed   char  int8_t;
typedef int (*o2o_pfunc_t)(int *, int);

typedef struct o2o_limit_motor_
{
	uint8_t  action;
	uint8_t  load_act;
	uint16_t load_val;

}o2o_limit_motor_t;

typedef union o2o_motor_
{
	uint8_t  load_act;
	uint16_t load_val;

}o2o_motor_t;
3、变量书写规划
  1. 使用全小写形式,单词与单词之间使用_连接;
  2. 为了防止与其它模块重名,建议全局变量加入前缀;
  3. 如果变量对属性或类型敏感,则可以加入组合标识;
    g+ 表示属性为全局变量;
    s+ 表示属性为静态变量;
    c+ 表示属性为只读变量;
    p+ 表示属性为指针;
    vo_ 表示空数据类型;(只针对空指针)
    xx_ 表示可变动类型;(根据应用场合可设定数据类型,例如外置存储器大小)
    un_ 表示共用体类型;
    ob_ 表示结构体类型;
    sc_、ss_、sl_ 分别为 1、2、4 字节有符号数类型;
    uc_、us_、ul_ 分别为 1、2、4 字节无符号数类型;
  4. 完整变量命名:前缀 + 属性&类型 + 描述

示范如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
int8_t             o2o_gsc_delay;  //如果局部变量则写法: sc_delay
int16_t            o2o_gss_delay;  //如果局部变量则写法: ss_delay
int32_t            o2o_gsl_delay;  //如果局部变量则写法: sl_delay
uint8_t            o2o_guc_delay;  //如果局部变量则写法: uc_delay
uint16_t           o2o_gus_delay;  //如果局部变量则写法: us_delay
uint32_t           o2o_gul_delay;  //如果局部变量则写法: ul_delay
uint32_t          *o2o_pul_delay;  //如果局部变量则写法: pul_delay (实际写法一般为 pul)
void              *o2o_pvo_delay;  //如果局部变量则写法: pvo_delay (实际写法一般为 pvo)
const int8_t       o2o_csc_delay;
static uint8_t     o2o_suc_delay;
o2o_limit_motor_t  o2o_gob_motor;  //如果局部变量则写法: ob_motor
o2o_limit_motor_t *o2o_pob_motor;  //如果局部变量则写法: pob_motor (可以简写为 p_motor)

对于平常时的使用,很少指出变量的类型,因为编程的重点在代码的业务逻辑及架构上。例如上面的变量统一写法为:delay motor g_delay g_motor p_delay p_motor即可。

4、代码书写规划
  1. 关键字与其它语句使用空格隔开,但else{}空置语句除外;
  2. 所有运算符都需要使用空格隔开;但for()条件判断除外;

示范如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
/**
  * @brief  EEPROM对象写操作
  * @param  *pob            要操作的EEPROM对象
  * @param  addr            要写入位置
  * @param  *pda            要写入的数据源
  * @param  len             要写入的数据长度
  * @return >0:操作成功
  */
int o2o_eeprom_write(o2o_eeprom_t *pob, uint32_t addr, uint8_t *pda, uint16_t len)
{
	int i;

	if (pda == 0) return;
	if (pob == 0) return;
	if (len == 0) return;
	if (addr >= O2O_EEPROM_SIZE) return;

	if ((pob == 0)
	&&  (pda == 0))
	{
		return;
	}
	else{}

	for (i=0; i<20; i++)
	{
		pob->cnt_h = i;
	}

	while (1)
	{
		i += 1;
		i++;
		i = 0;
	}

	do
	{
		pda = &i;
	}
	while (i > 0);

	switch (addr)
	{
		case 1:

			break;
		case 2:

			break;
		default:

			break;
	}
}

单词缩写

1、单词缩写字典
字母 描述 缩写词
A Average Avg
Addition Add
Accumulator Acc
Address Addr
Action Act
Active Act
Amplitude Amp
Analog Input AI
Anolog I/O AIO
All All
Alarm Alm
Allocate Alloc
Analog Output AO
Apparent App
Argument Arg
Arrange Arrng
Array Array
Assemble Asm
Attribute Attrib
B Back Bk
Background Bg
Break Brk
Bar Bar
Bit Bit
Block Blk
Buffer Buf
Button Btn
Bypass Bypass
C Calibration Cal
Calculate Calc
Configuration Cfg
Channel Ch
Change Chg
Check Chk
Clock Clk
Clear Clr
Clear Screen Cls
Command Cmd
Compare Cmp
Complete Comp
Count Cnt
Counter Ctr
Column Col
Communication Comm
Connect Con
Construct Cons
Control Ctrl
Context Ctx
Convert Conv
Copy Cp
Current Cur
Cursor Csr
Control Word CW
Color Cr(clr)
D Data Dat
Date Date
Day Day
Day-of-week DOW
Delay Dly
Debounce Debounce
Decrease Dec
Decimal Dec
Decode Decode
Define Def
Degree Deg
Delete Del
Destination Dst
Descriptor Desc
Device Dev
Discrete Input DI
Digit Dig
Discrete I/O DIO
Discrete Output(s) DO
Disable Dis
Display Disp
Discovery Disc
Division Div
Divisor/Division Div
Document Doc
Down Down
Dummy Dummy
Dynamic Dyn
E Edge Edge
Edit Edt
Effective Eff
Electric Elec
Empty Empty
Enable En
Engine Eng
Enter Enter
Entries Entries
Equivalent Equiv
Error(s) Err
Ethernet Eth
Engineering Units EU
Event(s) Event
Extension Ext
Exit Exit
Exception Exc
Expiration Exp
Exponent Exp
F Field Fld
Flag Flg
Flush Flush
Function(s) Fnct
Format Frm
Fraction Fract
Free Free
Frequency Freq
Full Full
G Grid Grd
Gain Gain
Get Get
Generate Gen
Group(s) Grp
H Handler Handler
Harmonic Harm
Hexadecimal Hex
High Hi
History Hist
Hit Hit
High Priority Task HPT
Hour(s) Hr
I I.D. Id
Idle Idle
Impulse Imp
Image Img
Increment Inc
Information Info
Initial Init
Insert Ins
Input(s) In
Initialization Init
Initialize Init
Instruction Instr
Interrupt Int
Invert Inv
Interrupt Service Routine ISR
Index Ix
K Key Key
Keyboard Kdb
L Label Lab
Length Len
List Lst(Ls)
Library Lib
Limit Lim
Low Lo
Lower Le
Lowest Lo
Lock Lock
Low Priority Task LTP
M Manager Mngr(mgr)
Magnitude Mag
Mantissa Man
Manual Man
Manufacture Mfg
Maximum Max
Mailbox Mbox
Minimum Min
Mode Mode
Month Month
Move Mov
Message Msg
Measure Meas
Mask Msk
Multiplication Mul
Multiplex Mux
Make Mk
N Negative Neg
Number of Num
Nesting Nesting
Neutral Neut
New New
Next Next
O Offset Offset
Old Old
Operation System OS
Optimize Opt
Original Orig
Output Out
Overflow Ovf
P Password Pwd
Picture Pic
Point Pt
Print Prn
Program Prg
Package Pkg
Parameter Param
Pass Pass
Performance Perf
Period Per
Phase Ph
Port Port
Position Pos
Positive Pos
Power Pwr
Previous Prev
Priority Prio
Printer Prt
process Proc
Product Prod
Protocol Prot
Pointer Ptr
Put Put
Q Queue Q
Quality Qlty
Quarter Quar
R Raw Raw
Reactive React
Recall Rcl
Rectangle Rect
Read Rd
Ready Rdy
Reference Ref
Register Reg
Request Req
Reset Reset
Reserve Resv
Resume Resume
Response Resp
Return Rtn
Reverse Revs
Ring Ring
Row Row
Repeat Rpt
Real-Time RT
Running Running
Receive Rx
S Server Srv
Source Src
Statistic Stat
String Str
Sybase Syb
Sample Smp
Scale Scale
Scale Factor SF
Scaling Scaling
Scan Scan
Schedule Sched
Scheduler Sched
Screen Scr
Second(s) Sec
Segment(s) Seg
Select Sel
Semaphore Sem
Sequence Seq
Server Svr
Set Set
Setting Setting
Signal Sig
Size Size
Seven-segments SS
Sourse Src
Start Start
Statistic(s) Stat
Status Stat
Stack Stk
Standard Std
Stop Stop
String Str
Subtraction Sub
Suspend Suspend
Switch Sw
Synchronize Synch
System Syst
T Temp Tmp
Text Txt
Task Task
Table Tbl
Threshold Th
Tick Tick
Time Time
Timer Tmr
Toggle Tgl
Total Tot
Trigger Trig
Time-stamp TS
Timeout TO
Unlock Unlock
U User Usr
Up Up
Update Update
Utility Util
V Value Val
Vector Vect
Version Ver
Variable Var
Visible Vis
Voltage Vol
W Watchdog Wdog(wdg)
Window Wnd(win)
Write Wr
Y Year Year