版权声明:本文为博主原创文章,转载请注明源地址。 https://cloud.tencent.com/developer/article/1433677
这阵子在C语言环境做开发,写了大量宏函数,写得头疼,但使用宏函数模板的确可以提高开发效率及代码质量,所以还得硬着头皮写,在一个偶然的机会发现有个叫P99的开源项目,P99提供了大量的的宏和函数定义,用于简化C编程,。说白了,P99提供的就是一大堆.h
头文件,.h
文件中定义了大量的宏函数,利用这些宏函数可以简化C代码开发。
比如下面用了P99中提供的例程实现了C++中才有的try-catch-finally语句:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <stdatomic.h>
#include <p99_try.h>
void test_try(){
unsigned char*volatile buffer = 0;
P99_TRY {
buffer = malloc(200);
if (!buffer) P99_THROW(thrd_nomem);
printf("return %s\n",__FUNCTION__);
// do something complicated with buffer
//favorite_func(buffer);
} P99_FINALLY {
free(buffer);
}
}
int main(void) {
test_try();
return EXIT_SUCCESS;
}
// 定义名为`enum_test`,包含`hello,world)`两个值的枚举类型
P99_DECLARE_ENUM(enum_test,hello,world);
宏展开后的代码
typedef enum enum_test { hello,world , \
/*! upper bound of the @ref T constants */ \
enum_test_amount, \
/*! the largest @ref T constant */ \
enum_test_max = ((size_t)(enum_test_amount) - 1u), \
/*! the smallest @ref T constant */ \
enum_test_min = 0 \
} enum_test; \
__attribute__((__const__)) \
__attribute__((__always_inline__)) __inline__ \
char const* enum_test_getname(enum_test p00_x) { \
switch ((uintmax_t)p00_x) { \
case hello: return "hello"; case world: return "world"; \
default: return "((" "enum_test" ")unknown value)"; \
} \
} \
extern void p00_harmless_declaration_declare_enum_getnameenum_test(void); \
__attribute__((__pure__)) \
__attribute__((__always_inline__)) __inline__ \
enum_test enum_test_parse(char const p00_s[]) { \
enum_test p00_ret = enum_test_amount; \
if (p00_s) { \
size_t p00_c = 0; \
size_t const p00_len = strlen(p00_s); \
if (!memcmp("hello", p00_s, p00_len)) { \
++p00_c; \
p00_ret = hello; \
}; if (!memcmp("world", p00_s, p00_len)) { \
++p00_c; \
p00_ret = world; \
}; \
if (p00_c > 1) p00_ret = enum_test_amount; \
} \
return p00_ret; \
} \
extern void p00_harmless_declaration_declare_enum_parseenum_test(void)
P99_DEFINE_STRUCT(struct_test,int hello,char* world);
展开后的代码
struct fl_buf_info { \
int hello; char* world; \
}; \
typedef int hello_P99_typedef_of_fl_buf_info;
typedef char* world_P99_typedef_of_fl_buf_info
P99_IS_ONE(first,...)
可以检查first
是否属于__VA_ARGS__
参数列表中的一个
// 先定义一个包含所有参数名的enum
P99_DECLARE_ENUM(enum_names,tom,jerry,sam,smith,trump,bill)
if (P99_IS_ONE(tom, jerry,sam,smith,trump,bill)) {
// one of the guys is 23, do something special
} else {
// handle the base case
}
// 定义一个函数声明
P99_PROTOTYPE (void,hello,int,void*);
展开
void (hello)(int,void*); \
typedef void hello_prototype_ret; \
typedef int hello_prototype_0; typedef void* hello_prototype_1
还有很多其他的功能不一一列举,参见p99手册 《P99 - Preprocessor macros and functions for C99 and C11
》。
为了快速熟悉P99的内容建议从分类说明入手《Modules》
p99提供的只是一堆头文件,所以从http://p99.gforge.inria.fr/ 这里下载p99.zip或p99.tgz解压到自己的项目文件夹下,并添加到include搜索路径就算安装完成了。
建立下载说明文档p99-html.zip到本地以便随时查看,内容实在太多,不看文档搞不清楚。