在C
语言里面,没有map
结构,只有一个简单的数组。因此,如果我们无法实现如下的映射:
1 2 3
| header["Content-Type"] = "text/html"; header["Connection"] = "close"; header["Host"] = "www.host.com";
|
我们只可以这样写:
1 2 3
| header[1] = "text/html"; header[2] = "close"; header[3] = "www.host.com";
|
但是,这样写可读性太差了。
好在C
语言提供了宏,我们可以这么做:
1 2 3 4 5 6 7
| #define CONTENT_TYPE 1 #define CONNECTION 2 #define HOST 3
header[CONTENT_TYPE] = "text/html"; header[CONNECTION] = "close"; header[HOST] = "www.host.com";
|
但是这么做也有一个问题,就是map
的name
和value
分散了。如果我们要修改或者增加新的name value
,那么就容易搞错位置。
所以我们有如下技巧:
1 2 3 4 5 6 7 8
| #define HTTP_HEADER_MAP(XX) \ XX(CONTENT_TYPE, "text/html") \ XX(CONNECTION, "close") \ XX(HOST, "www.host.com") \
#define HTTP_HEADER_VARS_GEN(name, value) char name[] = value; HTTP_HEADER_MAP(HTTP_HEADER_VARS_GEN) #undef HTTP_HEADER_VARS_GEN
|
我们来给一个完整的例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| #include <stdio.h>
#define HTTP_HEADER_MAP(XX) \ XX(CONTENT_TYPE, "text/html") \ XX(CONNECTION, "close") \ XX(HOST, "www.host.com") \
enum http_header_e { #define HTTP_HEADER_GEN(name, value) HTTP_HEADER_##name, HTTP_HEADER_MAP(HTTP_HEADER_GEN) #undef HTTP_HEADER_GEN };
int main(int argc, char const *argv[]) { char *header[3]; #define HTTP_HEADER_VARS_GEN(name, value) header[HTTP_HEADER_##name] = value; HTTP_HEADER_MAP(HTTP_HEADER_VARS_GEN) #undef HTTP_HEADER_VARS_GEN
printf("%s\n", header[HTTP_HEADER_CONTENT_TYPE]); printf("%s\n", header[HTTP_HEADER_CONNECTION]); printf("%s\n", header[HTTP_HEADER_HOST]);
return 0; }
|
这个技巧的大概思路是,我们通过宏定义一个伪map
,即HTTP_HEADER_MAP
。这个宏我们需要传递一个XX
,而这个XX
就根据我们的需求,来取HTTP_HEADER_MAP
里面的内容。
例如,在main
函数里面,我们定义了一个HTTP_HEADER_VARS_GEN
来替换XX
,而HTTP_HEADER_VARS_GEN
就是去取HTTP_HEADER_MAP
的东西,来初始化我们的header
数组。
明白了这个思想之后,我们可以定一个新的宏来生成printf
代码,从而继续简化我们的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| #include <stdio.h>
#define HTTP_HEADER_MAP(XX) \ XX(CONTENT_TYPE, "text/html") \ XX(CONNECTION, "close") \ XX(HOST, "www.host.com") \
enum http_header_e { #define HTTP_HEADER_GEN(name, value) HTTP_HEADER_##name, HTTP_HEADER_MAP(HTTP_HEADER_GEN) #undef HTTP_HEADER_GEN };
int main(int argc, char const *argv[]) { char *header[3]; #define HTTP_HEADER_VARS_GEN(name, value) header[HTTP_HEADER_##name] = value; HTTP_HEADER_MAP(HTTP_HEADER_VARS_GEN) #undef HTTP_HEADER_VARS_GEN
#define HTTP_HEADER_PRINTF_GEN(name, value) printf("%s\n", header[HTTP_HEADER_##name]); HTTP_HEADER_MAP(HTTP_HEADER_PRINTF_GEN) #undef HTTP_HEADER_PRINTF_GEN
return 0; }
|
可以发现,代码非常的简洁了。
总结一下套路:
- 定义一个伪
map
- 定义一个
GEN
宏
- 把这个
GEN
宏传递进伪map
里面,从这个伪map
里面取我们需要的内容