前言
前两天由于工作需要,要用C语言生成类似C++ template的效果。大致的思路我是知道的——用C语言的宏实现,但是说到细节,就不甚了解了。之前看的达内的一个老师讲STL的视频。他在视频里好像做过类似的事情。凭着对视频的记忆以及以前用C语言宏的经验,我也尝试着做了做。最后呈现的效果还不错。写个文章记录一下。
一、目标
我要实现的是根据界面设置的大小,来生成一个对应大小的数组,该数组在一个结构体中。并且生成读写该结构体的函数。当然这是我简化的版本,我实际做的工作,比这要复杂。
二、实现步骤
1.头文件部分
代码如下(示例):
#define ARRAY_HEAD(name,size) \
typedef struct _arr_##name{ \
UInt8 index; \
UInt8 arr_##name[size]; \
}arr_##name; \
extern UInt8 get_arr_##name_by_index(arr_##name* arr_var,UInt8 index); \
extern void set_arr_##name_by_index(arr_##name* arr_var,UInt8 index,UInt8 val);
#define CALL_GET_ARR_FUNC(name) get_arr_##name_by_index
#define CALL_SET_ARR_FUNC(name) set_arr_##name_by_index
#define DEFINITION_VARIABLE(name) arr_##name
ARRAY_HEAD中的name参数,是一个标识。 类似于ID的功能。
2.源代码部分
代码如下(示例):
#define ARRAY_SOURCE(name) \
UInt8 get_arr_##name_by_index(arr_##name* arr_var,UInt8 index) \
{\
arr_var->index = index; \
return arr_var->arr_##name[index]; \
}\
void set_arr_##name_by_index(arr_##name* arr_var,UInt8 index,UInt8 val) \
{\
arr_var->index = index;\
arr_var->data[index] = val;\
}
3.调用部分
有了上面的宏定义,就可以生成代码了。
在头文件中调用ARRAY_HEAD宏。
代码如下(示例):
ARRAY_HEAD(ARRAY_1,20)
ARRAY_HEAD(ARRAY_2,30)
在源文件中调用ARRAY_SOURCE宏。
ARRAY_SOURCE(ARRAY_1)
ARRAY_SOURCE(ARRAY_2)
这样就声明了两个数组,长度分别是20、30. 注意是声明了,不是定义了。并且生成了操作这两种数组的函数。
下面的代码才是定义变量和使用变量。
DEFINITION_VARIABLE(ARRAY_1) var;
CALL_SET_ARR_FUNC(ARRAY_1)(&var,0,0);
CALL_SET_ARR_FUNC(ARRAY_1)(&var,1,1);
UInt8 data = CALL_GET_ARR_FUNC(ARRAY_1)(&var,1);
不知道上面的代码,大家能不能看懂。 不好理解的话,可以用编译器展开代码。
GCC的宏展开指令是 -E 调用格式如下:
GCC -E TestArray.c -o TestArray.i
总结
由于C语言的语言特性,在用C语言写的一些第三方库中,有大量的宏。 比如微软的MFC架构,就用了很多宏。在某些时候,用宏是挺方便。