![C语言最佳实践](https://wfqqreader-1252317822.image.myqcloud.com/cover/885/53286885/b_53286885.jpg)
1.7 实例分析
1.7.1 PurC函数库头文件
下面通过查看笔者维护的开源HVML解释器PurC的purc.h
头文件中的部分内容,来对本章所述的优良编码风格做进一步的解释。
![](https://epubservercos.yuewen.com/6E3F09/31751192203413306/epubprivate/OEBPS/Images/tx005.jpg?sign=1739334601-6URgEAThOxngg0E6l79mRpM4K0ElVALj-0-91b3af2b73707bc0ec51a6b1432df530)
首先是一段Doxygen格式的注释,其中包含了文件名、作者、日期、简介、版权声明等信息。注意,Doxygen格式的注释一般以/**
开始。
/** * @file purc.h * @author Vincent Wei * @date 2021/07/02 * @brief The main header file of PurC. * * Copyright (C) 2021, 2022 FMSoft * * This file is a part of PurC (short for Purring Cat), an HVML interpreter. * Licensed under LGPLv3+. */
之后,作为PurC函数库的主头文件,其中包含了其他必要的系统头文件以及PurC函数库的其他头文件。然后是一个结构体的定义,该结构体被定义为一个新的数据类型,同时使用Doxygen格式的注释来描述其成员的含义。
/** * purc_instance_extra_info: * * The structure defines the extra information for a new PurC instance. */ typedef struct purc_instance_extra_info { /** * ... */ purc_rdrcomm_k renderer_comm; /** * ... */ const char *renderer_uri; /** The SSL certification if using Secured WebSocket. */ const char *ssl_cert; /** The SSL key if using Secured WebSocket. */ const char *ssl_key; /** The default workspace of this instance. */ const char *workspace_name; /** The title of the workspace. */ const char *workspace_title; /** * ... */ const char *workspace_layout; } purc_instance_extra_info;
我们可以清晰地看到,PurC函数库的接口使用了K&R命名法。注意上述结构体中的purc_rdrcomm_k renderer_comm
成员,从类型名使用_k
后缀可以看出,该成员是一个枚举量,对应的枚举类型则定义在另一个头文件(purc-pcrdr.h
)中:
![](https://epubservercos.yuewen.com/6E3F09/31751192203413306/epubprivate/OEBPS/Images/tx006.jpg?sign=1739334601-dwmISjN7NkCdMKqc7oBK8CcPEUPo9yjQ-0-43cefddba829e797889934803d4f3bfa)
/* Renderer communication types */ typedef enum { PURC_RDRCOMM_HEADLESS = 0, #define PURC_RDRCOMM_NAME_HEADLESS "HEADLESS" PURC_RDRCOMM_THREAD, #define PURC_RDRCOMM_NAME_THREAD "THREAD" PURC_RDRCOMM_SOCKET, #define PURC_RDRCOMM_NAME_SOCKET "SOCKET" PURC_RDRCOMM_HIBUS, #define PURC_RDRCOMM_NAME_HIBUS "HIBUS" } purc_rdrcomm_k;
回到purc.h
头文件。再往下是宏定义:
#define PURC_HAVE_UTILS 0x0001 #define PURC_HAVE_DOM 0x0002 #define PURC_HAVE_HTML 0x0004 #define PURC_HAVE_XML 0x0008 #define PURC_HAVE_VARIANT 0x0010 #define PURC_HAVE_EJSON 0x0020 #define PURC_HAVE_FETCHER 0x0200 #define PURC_HAVE_FETCHER_R 0x0400 #define PURC_HAVE_ALL ( \ PURC_HAVE_UTILS | \ PURC_HAVE_DOM | \ PURC_HAVE_HTML | \ PURC_HAVE_XML | \ PURC_HAVE_VARIANT | \ PURC_HAVE_EJSON | \ PURC_HAVE_FETCHER | \ PURC_HAVE_FETCHER_R) #define PURC_MODULE_UTILS (PURC_HAVE_UTILS) #define PURC_MODULE_DOM (PURC_MODULE_UTILS | PURC_HAVE_DOM) #define PURC_MODULE_HTML (PURC_MODULE_DOM | PURC_HAVE_HTML) #define PURC_MODULE_XML (PURC_MODULE_DOM | PURC_HAVE_XML) #define PURC_MODULE_VARIANT (PURC_MODULE_UTILS | PURC_HAVE_VARIANT) #define PURC_MODULE_EJSON (PURC_MODULE_VARIANT | PURC_HAVE_EJSON) #define PURC_MODULE_ALL 0xFFFF
所有的宏都采用下画线连接的全大写单词形式,并使用PURC_
作为前缀;代码行严守了“80列”这条红线,并通过空行、续行和适当的缩进,让排版整齐,使得整个代码清晰易读。
下面查看其中的3个函数接口:前两个用于初始化一个PurC实例,第三个用于清理一个PurC实例。
PCA_EXPORT int purc_init_ex(unsigned int modules, const char *app_name, const char *runner_name, const purc_instance_extra_info *extra_info); static inline int purc_init(const char *app_name, const char *runner_name, const purc_instance_extra_info *extra_info) { return purc_init_ex(PURC_MODULE_ALL, app_name, runner_name, extra_info); } PCA_EXPORT bool purc_cleanup(void);
这3个函数的原型定义符合本章所讨论的编码风格。比如,purc_init_ex()
和purc_init()
两个函数均具有purc_
前缀,表示指针的星号出现在形参名称的前面;为严守“80列”这条红线,函数原型声明中的参数列表被分行书写;等等。作为PurC函数库的公开接口,原头文件中包含了对以上函数的接口描述。
注意purc_init()
函数被定义为调用purc_init_ex()
函数的内联函数,因而使用static
inline
关键词来修饰其原型。而_ex
后缀通常用于表示扩展(extended);也就是说,purc_init_ex()
函数是purc_init()
函数的扩展版本。