版权声明:本文为博主原创文章,转载请注明源地址。 https://cloud.tencent.com/developer/article/1433677
这阵子在C语言环境做开发,写了大量宏函数,写得头疼,但使用宏函数模板的确可以提高开发效率及代码质量,所以还得硬着头皮写,在一个偶然的机会发现有个叫P99的开源项目,P99提供了大量的的宏和函数定义,用于简化C编程,。说白了,P99提供的就是一大堆.h
头文件,.h
文件中定义了大量的宏函数,利用这些宏函数可以简化C代码开发。
比如下面用了P99中提供的例程实现了C 中才有的try-catch-finally语句:
代码语言:javascript复制#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 %sn",__FUNCTION__);
// do something complicated with buffer
//favorite_func(buffer);
} P99_FINALLY {
free(buffer);
}
}
int main(void) {
test_try();
return EXIT_SUCCESS;
}
定义enum
代码语言:javascript复制// 定义名为`enum_test`,包含`hello,world)`两个值的枚举类型
P99_DECLARE_ENUM(enum_test,hello,world);
宏展开后的代码
代码语言:javascript复制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)
定义struct
代码语言:javascript复制P99_DEFINE_STRUCT(struct_test,int hello,char* world);
展开后的代码
代码语言:javascript复制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
}
函数声明
代码语言:javascript复制// 定义一个函数声明
P99_PROTOTYPE (void,hello,int,void*);
展开
代码语言:javascript复制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到本地以便随时查看,内容实在太多,不看文档搞不清楚。
参考资料
《P99_TRY》
《P99_IS_ONE》