C 语言 宏定义 :字符串化 stringify 的应用
字符串化
-
通过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语言的宏非常的多,有些宏定义,使用起来跟函数相差不多,有些宏的使用,大大简化了代码量,让代码看起来非常的整洁美观
-
当然过多的【宏】,依旧需要不断的查看展开的效果,过长的的【宏定义】,加大了代码阅读的难度,让代码晦涩难懂
-
宏定义的函数,不利于软件【单步调试】
相关文章:
C 语言 宏定义 :字符串化 stringify 的应用
字符串化 通过C 语言的宏(MICRO),可以把数值或者一段字符的组合,转换为字符串。 因为 C语言的宏在【预处理】阶段就展开了,所以可以实现一些比较使用的功能,比如一些数据的初始化操作 比如定义一个宏&…...
代替swagger的api接口神器
自动化API文档-APIFOX 文章作者:老杨 一:概述 大家在后端开发开发过程中,最痛恨的两天事情:1.写文档,2.别人不写文档。而我们后端开发,必定经历的事情就是要和前端&测试对接,我们需要把我…...
2月12日,30秒知全网,精选7个热点
///北京首批29家药店开通异地参保直接结算服务试点药店已覆盖北京市东城区、西城区、朝阳区、海淀区、丰台区和石景山区,为来京就医的外省市参保人员提供便利///杭州召开平台经济健康高质量发展座谈会落实更有针对性的政策供给、提供“店小二”“保姆式”服务、建立…...
HTML img和video object-fit 属性
简介 Css中object-fit主要是应用到img标签和Video标签的,来控制显示缩放效果的。 首先我们存在一张图片,原始图片的尺寸是 1080px x 600px, 展示效果如下: 如果我们的css样式中的img大小设定并不能满足图片的原始大小,比如我们的…...
Pascal版本的 - freopen
参数 filename -- 这是包含要打开的文件的名称的字符串。 mode -- 这是包含文件访问模式的字符串。它包括 - 高级编号模式&说明1个 “r” 打开文件进行读取。该文件必须存在。 2个 “w” 创建一个用于写入的空文件。如果已存在同名文件,则删除其内容并将该文件…...
STM32单片机OLED显示
OLED接口电路STM32单片机OLED显示程序源代码#include "sys.h"#define OLED_RST_Clr() PCout(13)0 //RST#define OLED_RST_Set() PCout(13)1 //RST#define OLED_RS_Clr() PBout(4)0 //DC#define OLED_RS_Set() PBout(4)1 //DC#define OLED_SCLK_Clr()PCout(15)0 //SCL…...
备战金三银四,软件测试面试题(全)
1.B/S架构和C/S架构区别 B/S 只需要有操作系统和浏览器就行,可以实现跨平台,客户端零维护,维护成本低,但是个性化能力低,响应速度较慢 C/S响应速度快,安全性强,一般应用于局域网中,因…...
硬件篇-配置
机箱->239元 机箱选用的itx迷你机箱,为了后期nas方便拓展选了4盘位,该机箱还是比较符合我的预期的,颇有种麻雀虽小五脏俱全的感觉,机箱可以安装matx主板和itx主板,还是比较方便的,机箱带三个大散热风扇&…...
网页内容 中文乱码 解决办法
原因 是因为没有网页没有设置charset是utf-8 解决办法 <!DOCTYPE html> <html lang"en"><head><!-- 这一个标签不能少 --><meta charset"UTF-8" /><body></body> </html>...
【C++之容器篇】造轮子:模拟实现vector类
目录前言一、项目结构1. vector的简介2. 项目结构二、vector的底层结构三、默认成员函数(Member functions)1. 构造函数(1)无参构造函数(2)使用n个值来构造对象(3)使用一段迭代器区间来进行初始化(4)测试构造函数2. 拷贝构造函数(现代写法)3. 析构函数4.…...
C++中的右值引用与移动构造函数
1.右值引用右值引用是 C11 引入的与 Lambda 表达式齐名的重要特性之一。它的引入解决了 C 中大量的历史遗留问题, 消除了诸如 std::vector、std::string 之类的额外开销, 也才使得函数对象容器 std::function 成为了可能。1.1左值、右值的纯右值、将亡值…...
Swift如何使用依赖注入进行解藕
Swift 中可以使用依赖注入(Dependency Injection)来解耦组件之间的依赖关系。依赖注入是一种设计模式,指的是在运行时,将一个组件所依赖的其他组件通过构造函数或者属性注入的方式传递给该组件。 例如,有两个组件 A 和…...
合宙ESP32S3-CORE开发板|保姆级|Arduino IDE|windows11|esp32S3支持库|helloword例程:Arduino 环境搭建
Arduino主页网址: Software | Arduino 以windows11版本为例: Arduino IDE最新版本为2.0.3 左边的按钮是直接下载(免捐赠): 下载安装完成后,更改软件默认语言: 默认的库是不支持ESP32的&#…...
CMake中target_precompile_headers的使用
CMake中的target_precompile_headers命令用于添加要预编译的头文件列表,其格式如下: target_precompile_headers(<target><INTERFACE|PUBLIC|PRIVATE> [header1...][<INTERFACE|PUBLIC|PRIVATE> [header2...] ...]) # 1 target_preco…...
SpringCloud和微服务介绍
SpringCloud介绍 SpringCloud是在SpringBoot的基础上构建的,用于简化分布式系统构建的工具集。 该工具集为微服务架构中所涉及的配置管理,服务发现,智能路由,断路器,微代理和控制总线等操作提供了一种简单的开发方式。 SpringCloud中包含了多个子项目: Spring …...
Qt源码编译过程中配置文件中的选项说明
文章目录选项说明默认值顶级安装目录-prefix 部署目录,如目标设备上所示。/usr/local/Qt-$QT_VERSION-extprefix 安装目录,如主机上所示。SYSROOT/PREFIX-hostprefix [dir]主机上运行的生成工具的安装目录。如果未给定[dir],则将使用当前构建…...
Mysql 增删改查(一) —— 查询(条件查询where、分页limits、排序order by、分组 group by)
查询 select 可以认为是四个基本操作中使用最为频繁的操作,然而数据量比较大的时候,我们不可能查询所有内容,我们一般会搭配其他语句进行查询: 假如要查询某一个字段的内容,可以使用 where假如要查询前几条记录&#…...
VScode 结合clangd 构建linux源代码阅读环境
1、背景介绍上一篇文章:VScode 结合Global构建linux源代码阅读环境 ,介绍了在VS Code工具中通过remote-ssh远程登陆到Linux远程服务器,使用Global构建linux源代码阅读环境,对linux kernel代码进行解析,实现全局搜索、自…...
web应用 —— JavaScript
Web应用(acwing) 三、JavaScript 1.JS的调用方式与执行顺序 ①使用方法 HTML页面中任意位置加上<script type"module"></script>标签即可 常见使用方式: 直接在<script type"module"></script>标签内写JS代码。直…...
SSM整合SpringSecurity简单使用
一、SpringSecurity 1.1 什么是SpringSecurity Spring Security 的前身是 Acegi Security ,是 Spring 项目组中用来提供安全认证服务的框架。(官网地址) Spring Security 为基于J2EE企业应用软件提供了全面安全服务。特别是使用领先的J2EE解决方案-Spring框架开发…...
电工必看:正弦交流电路中的相量法实战技巧(附计算示例)
电工必看:正弦交流电路中的相量法实战技巧(附计算示例) 在电气工程领域,正弦交流电路的分析是每位电工和电气工程师必须掌握的核心技能。面对复杂的电路计算,传统的三角函数解析法往往让从业者陷入繁琐的运算泥潭。相量…...
极域电子教室破解神器:JiYuTrainer 让课堂学习更自由高效
极域电子教室破解神器:JiYuTrainer 让课堂学习更自由高效 【免费下载链接】JiYuTrainer 极域电子教室防控制软件, StudenMain.exe 破解 项目地址: https://gitcode.com/gh_mirrors/ji/JiYuTrainer 你是否厌倦了在计算机课堂上被极域电子教室完全控制…...
Android开发避坑指南:registerForActivityResult找不到?可能是依赖版本惹的祸
Android开发实战:全面解析registerForActivityResult的正确使用与版本适配 在Android应用开发中,Activity之间的数据传递一直是核心功能之一。随着Jetpack组件的不断演进,Google推出了registerForActivityResult这一现代化API来替代传统的sta…...
基于RAG的智能客服系统实战:从架构设计到生产环境优化
最近在做一个智能客服系统的升级项目,之前用规则引擎维护起来太痛苦了,纯用大模型又贵又不准。经过一番折腾,最终用RAG(检索增强生成)技术搞定了,效果提升非常明显。今天就来分享一下从架构设计到上线优化的…...
Element React深度解析:企业级React组件库的架构设计与实战应用
Element React深度解析:企业级React组件库的架构设计与实战应用 【免费下载链接】element-react Element UI 项目地址: https://gitcode.com/gh_mirrors/el/element-react Element React是一款基于React框架构建的企业级UI组件库,它为开发者提供了…...
java的for循环
public class Demo6 {public static void main(String[] args) {for (int money1;money<10;money){System.out.println("换一元纸币"money"张。换5角硬币"(10-money)*2"个");}} }public class Demo8 {public static void main(String[] args)…...
2026 年智慧工地排名榜单第一|山东建安物联科技有限公司
2026 年度智慧工地综合实力榜单正式揭晓,山东建安物联科技有限公司(大建安)凭借标准引领、技术实力与标杆项目,登顶全国榜首,成为行业公认的智慧工地领军企业。公司打造的中建八局烟台崆峒胜境项目,获评国家…...
怎么看待OpenClaw?
特别附:"词元"为何是理解这一切的关键引言:一只龙虾爬到Linux头顶2026年3月,GitHub星标榜上出现了一个奇观——一只"龙虾"爬到了Linux头顶。OpenClaw,这个从个人项目演变成的AI智能体框架,在不到四…...
Java 核心四大基石:从 Object 源码到包装类陷阱的全维度复盘
让我们从两个常见的实际场景出发,看看开发者会遇到什么困惑。 场景一:如何在程序中获取“当前时间”? 你一定见过这样的界面: 直播画面右上角显示:2026 年 01 月 08 日 15:00:00(实时更新) 这个…...
Windows音频捕获终极革命:告别系统混音器,实现进程级精准录音
Windows音频捕获终极革命:告别系统混音器,实现进程级精准录音 【免费下载链接】win-capture-audio An OBS plugin that allows capture of independant application audio streams on Windows, in a similar fashion to OBSs game capture and Discords …...
