押注网站建设南京市环保局官方南京做网站
字符串化
-  
通过C 语言的宏(MICRO),可以把数值或者一段字符的组合,转换为字符串。
 -  
因为 C语言的宏在【预处理】阶段就展开了,所以可以实现一些比较使用的功能,比如一些数据的初始化操作
 -  
比如定义一个宏,传入的宏的参数是一个 func 函数名,经过宏的层层处理,可以把这个函数名以字符串的方式取出来,并赋值给结构体的 字符指针成员
 
示例:
        struct rt_init_desc{const char* fn_name;const init_fn_t fn;};#define INIT_EXPORT(fn, level)                                                       \const char __rti_##fn##_name[] = #fn;                                            \RT_USED const struct rt_init_desc __rt_init_desc_##fn SECTION(".rti_fn." level) = \{ __rti_##fn##_name, fn};
 
-  
这里的 INIT_EXPORT 的 作用是 在 段中初始化一个数据结构:代码可以通过变量多个这样的数据结构,获取可执行函数的指针,从而实现 【自动初始化】机制。
 -  
这个操作有两个特点:(1)代码得到简化 (2)
fn函数名【字符串化】然后组合成一个新的字符串,对数据成员const char *fn_name进行初始化 
字符串化
-  
宏定义中,通过一个
#就可以把 一串字符,转换为字符串,这里的一串字符,可以是一个数值,可以是一个函数指针(函数名) -  
如:
#fn,就把fn这个参数,转换为 C 语言中的字符串(常量)了 -  
字符串化最经典的 转换宏:
 
#define __stringify_1(x...)     #x
#define __stringify(x...)       __stringify_1(x)
 
-  
__stringify_1(5)获取的 是"5",也就是5转换为 字符串"5"了 -  
__stringify的作用更强大,如果传入的参数也是个【宏定义】,会继续展开,并转换 
#define STRING_NAME             "5"
#define DEV_DEMO_NAME1           __stringify(STRING_NAME)
 
这时
DEV_DEMO_NAME1不再是 字符串 “STRING_NAME”,而是 “5”
字符串连接
-  
宏定义中,通过两个
##可以把两个字符串连接起来,也就是【拼接】起来 -  
__rti_##fn##_name, 如果 fn 为hello,则 展开后为__rti_hello_name,这里的##起到了字符串(拼接)连接的作用,展开后##就不存在了 
测试一下
#include <stdio.h>#define __stringify_1(x...)     #x
#define __stringify(x...)       __stringify_1(x)#define STRING_NAME             "5"
#define DEV_DEMO_NAME           __stringify(5)
#define DEV_DEMO_NAME1           __stringify(STRING_NAME)
#define DEV_DEMO_NAME2          __stringify(DEVICE_NAME_HELLO)int main()
{printf("%s  enter\n", __func__);printf("%s : DEVICE_NAME : %s \n", __func__, STRING_NAME);printf("%s : DEV_DEMO_NAME : %s \n", __func__, DEV_DEMO_NAME);printf("%s : DEV_DEMO_NAME1 : %s \n", __func__, DEV_DEMO_NAME1);printf("%s : DEV_DEMO_NAME2 : %s \n", __func__, DEV_DEMO_NAME2);return 0;
}
 
-  
测试环境为:ubuntu 20.04 Linux 环境
 -  
编译:
$ gcc micro_string_test.c -o micro_string_test -  
运行效果:
 
zhangsz@zhangsz-virtual-machine:~/linux/codes/202302/0212$ ./micro_string_test 
main  enter
main : DEVICE_NAME : 5 
main : DEV_DEMO_NAME : 5 
main : DEV_DEMO_NAME1 : "5" 
main : DEV_DEMO_NAME2 : DEVICE_NAME_HELLO 
 
- 简单的解释: 
#define STRING_NAME "5"直接定义一个字符串"5",而不是数值5 __stringify(5)的作用把5转换为 字符串了,这就是普通的 【字符串化】#define DEV_DEMO_NAME2 __stringify(DEVICE_NAME_HELLO),由于DEVICE_NAME_HELLO不是一个可以展开的【宏】,所以依旧转换为普通的字符串DEVICE_NAME_HELLO#define DEV_DEMO_NAME1 __stringify(STRING_NAME),由于STRING_NAME是个宏,内容是"5",所以再次展开为"5",而不是STRING_NAME,注意这个"5"是有双引号的,因为【宏】是【替换】
小结
-  
在操作系统中,C语言的宏非常的多,有些宏定义,使用起来跟函数相差不多,有些宏的使用,大大简化了代码量,让代码看起来非常的整洁美观
 -  
当然过多的【宏】,依旧需要不断的查看展开的效果,过长的的【宏定义】,加大了代码阅读的难度,让代码晦涩难懂
 -  
宏定义的函数,不利于软件【单步调试】
 
