关于C代码规范,如何制定自己的编码规范

目录

1、简介

2、代码规范

2.1 文件布局:

        源文件模板(xxx.c)

        头文件模板(xxx.h)

2.2 命名

2.3 注释

3、代码格式工具的使用 

4、C语言常用单词缩写

参考资料


1、简介

        ”C语言是一个非常适合简洁编程的语言,但很多程序员对于简洁的关注很容易掩盖代码的真正含义”,也就是说人们都会以最快、最简洁的方式去将代码实现出来,从而忽视了代码规范,这就导致了,代码是我今天写的,但是过了一段时间我就很难理解这一段代码了。

        “一个专业的程序员不仅因该能写出有效和正确的代码,他还因该能以一种可能在多年以后,需要维护它的人能够理解的风格编写的代码”。所以不管是自己独立开发的项目,还是与其他人共同开发的项目,都应该做好代码规范,这样开发和维护的过程就也会变得轻松一点。

2、代码规范

        下面的代码规范主要是为自己编程制定的,这里做一个例子方便演示。更多的细节参考书籍《C Style: Standarts and Guidenlines》,这个在已最后的参考资料中给出连接。

2.1 文件布局:

        如果没有对大型项目的文件进行分类,那么寻找一个文件一困难的。文件的分类布局是一个项目的开始。

        第一步是划分层级(目录),以一个 STM32 的工程举例,可能这个工程包含驱动层、HAL层、App层、GUI层、lib层等,那么工程基本目录结构如图下图左边所示,文件的命名如下图右边所示,每个文件以”层级名_模块.c”的形式,如写了一个配置串口的代码,串口属于驱动层,所以将它放到 Drv 目录下,文件名为“drv_usrt.c”。

         第二文件的命名和放置位置如上图所以,需要注意的是:处于低层级的函数不能调用高层级的函数,如 Hal 层里面的函数可以调用 Drv 层的函数,而 Drv 层的函数不能调用 Hal 层的函数,层级函数的调用关系如下图,Lib 层的函数可以被整个工程调用。

        源文件模板(xxx.c)

/************************************************************************
 * FilePath     : lib_log.c
 * Author       : GX.Duan
 * Date         : 2022-09-21 22:22:33
 * LastEditTime : 2022-09-21 22:28:41
 * LastEditors  : ShallowGreen123 2608653986@qq.com
 * Copyright (c): 2022 by GX.Duan, All Rights Reserved.
 * Github       : https://github.com/ShallowGreen123/lvgl_mydemo
 ************************************************************************/
#define __LIB_LOG_C__
/*********************************************************************************
 *                                  INCLUDES
 * *******************************************************************************/
#include "lib_log.h"

/*********************************************************************************
 *                                   DEFINES
 * *******************************************************************************/

/*********************************************************************************
 *                                   MACROS
 * *******************************************************************************/

/*********************************************************************************
 *                                  TYPEDEFS
 * *******************************************************************************/

/*********************************************************************************
 *                              STATIC FUNCTION
 * *******************************************************************************/

/*********************************************************************************
 *                              GLOBAL FUNCTION
 * *******************************************************************************/

        头文件模板(xxx.h)

/************************************************************************
 * FilePath     : drv_log.h
 * Author       : GX.Duan
 * Date         : 2022-09-21 22:22:43
 * LastEditTime : 2022-09-21 22:22:59
 * LastEditors  : ShallowGreen123 2608653986@qq.com
 * Copyright (c): 2022 by GX.Duan, All Rights Reserved.
 * Github       : https://github.com/ShallowGreen123/lvgl_mydemo
 ************************************************************************/
#ifndef _LIB_LOG_H_
#define _LIB_LOG_H_

/*********************************************************************************
 *                                  INCLUDES
 * *******************************************************************************/
#include <stdio.h>
#include <string.h>
#include <stdint.h>

/*********************************************************************************
 *                                   DEFINES
 * *******************************************************************************/
#ifdef __LIB_LOG_C__
#    define DEF_EXT
#else
#    define DEF_EXT extern
#endif

/*********************************************************************************
 *                                   MACROS
 * *******************************************************************************/

/*********************************************************************************
 *                                  TYPEDEFS
 * *******************************************************************************/

/*********************************************************************************
 *                              GLOBAL PROTOTYPES
 * *******************************************************************************/


#endif /* _LIB_LOG_H_ */

2.2 命名

        函数命名:层级名+模块名+功能名,如 Drv_UartSend(void); Drv_UartRecv(void); 层级名和模块名之间用“_”隔开,模块名和功能名采用“大驼峰命名法”。

void Drv_UartSend(void)
{}

void Drv_UartRecv(void)
{}

        全局变量:层级名+模块名+变量名,Drv_UartSendByteCnt; Drv_UartRecvByteCnt; 层级名和模块名之间用“_”隔开,模块名和变量名采用“大驼峰命名法”。(全局变量加上 static 修饰,通过函数的形式访问。滥用全局变量的危害

uint32_t Drv_UartSendByteCnt; 

uint32_t Drv_UartRecvByteCnt; 

        局部变量:局部变量采用全小写,单词之间用 "_" 隔开的方式,如 uint8_t tmp; uin32_t array_idx; 函数内部的循环变量可以使用 i、j等,但不要让这样的变量命名周期过长。

void Drv_I2cTestFun(void)
{
    uint8_t tmp; 
    uin32_t array_idx; 
    ......
} 

        结构体/联合体(共用体):层级名_模块名_结构体名_t,结构体成员采用“大驼峰命名法” ,使用 typedef 新的结构体名因全部大写,联合体只需要把关键字 struct 改为 union 即可,如下所示。

// The typedef is not used    
struct drv_uart_handle_t {
    uint8_t  Member1;
    uint16_t RecvCnt;
    uint32_t SendCnt;
    ......
};

// typedef is used
typedef struct drv_uart_handle_t {
    uint8_t  Member1;
    uint16_t RecvCnt;
    uint32_t SendCnt;
    ......
}DRV_UART_HANDLE_T;

        枚举:层级名_模块名_枚举名_t,枚举成员采用全部大写的方式 ,使用 typedef 新的结构体名因全部大写,如下所示。

enum drv_uart_type_e {
    DRV_UART_TYPE_WIFI,
    DRV_UART_TYPE_BLE,
    DRV_UART_TYPE_VCP,
    ......
};

typedef enum drv_uart_type_e {
    DRV_UART_TYPE_WIFI,
    DRV_UART_TYPE_BLE,
    DRV_UART_TYPE_VCP,
    ......
}DEV_UART_TYPE_E;

        宏定义:DEF_层级名_模块名_宏名;宏定义采用全大写。

#define DEF_DRV_UART_BUFF_LEN      1024
#define DEF_LIB_MATH_MAX((a),(b)) (((a) > (b))? (a) : (b))

2.3 注释

        关于注释的部分,引用原文的中一段话,如下所示。“厉害的程序员不需要写注释(doge),代码的逻辑是显而易见的”。只要遵循代码规范,然后跟着实现的步骤一步步看,代码本身的逻辑也就清楚了。

        如下面这个函数,首先它是 Lib 层的,属于 log 模块的,功能是根据不同 log 等级输出不同颜色的日志。以变量 str 的第一个字符作为日志等级,然后赋予输出的颜色,最后打印出来。感觉是不是不用注释,可能这个比较简单。理论上,敲代码是不需要注释的,注释留给维护的人写就好了,如果维护人员写不出来,那说明编程能力和代码规范能力还需要提升。

void Lib_LogColorPrintf(void *str, void *prefix)
{
    char  type      = *((char *)prefix + 1);

    /* clang-format off */
    switch (type) {
        case 'V': printf(DEF_LIB_LOG_BRIGHT_YELLOW); break;
        case 'D': printf(DEF_LIB_LOG_BRIGHT_GREEN); break;
        case 'I': printf(DEF_LIB_LOG_BRIGHT_WHITE); break;
        case 'W': printf(DEF_LIB_LOG_BRIGHT_YELLOW); break;
        case 'E': printf(DEF_LIB_LOG_BRIGHT_RED); break;
        case 'X' :printf(DEF_LIB_LOG_BRIGHT_MAGENTA); break;
        default:
            break;
    }
    /* clang-format on */
    printf("%s\n", (uint8_t *)str);
    printf(DEF_LIB_LOG_COLOR_RESET);
}

        最后,那些编程界的大佬们费尽心思设计出了各种的高级语言,其中一个原因是想提高代码的可读性,降低编程的门槛,如果没有这些高级语言,好吧......, 已经想象到程序员面对机器码、汇编时的绝望了。所以我们还是需要了解一些编程上的规范,避免将代码写成天书,避免将可读性高的语言写出没有可读性的代码,这样不就辜负了编程大佬的努力了吗。所以要好好学习代码规范,写出自己风格的代码。                     

3、代码格式工具的使用 

        这个直接在本站搜索 clang-format 的使用就可以,因该还是有比较多的解释它是怎使用的。

4、C语言常用单词缩写

        单词缩写这一块建议能用缩写就用缩写,当然缩写得是那种广为人知的才可以用,不是常用的缩写还是用全拼。

        参考文档 :https://download.csdn.net/download/ShallowGreen/86729786

参考资料

代码规范文档:C Style: Standarts and Guidelines

代码格式检查工具:https://clang.llvm.org/docs/ClangFormatStyleOptions.html

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值