当前位置: 首页 > news >正文

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 语言的宏&#xff08;MICRO&#xff09;&#xff0c;可以把数值或者一段字符的组合&#xff0c;转换为字符串。 因为 C语言的宏在【预处理】阶段就展开了&#xff0c;所以可以实现一些比较使用的功能&#xff0c;比如一些数据的初始化操作 比如定义一个宏&…...

代替swagger的api接口神器

自动化API文档-APIFOX 文章作者&#xff1a;老杨 一&#xff1a;概述 大家在后端开发开发过程中&#xff0c;最痛恨的两天事情&#xff1a;1.写文档&#xff0c;2.别人不写文档。而我们后端开发&#xff0c;必定经历的事情就是要和前端&测试对接&#xff0c;我们需要把我…...

2月12日,30秒知全网,精选7个热点

///北京首批29家药店开通异地参保直接结算服务试点药店已覆盖北京市东城区、西城区、朝阳区、海淀区、丰台区和石景山区&#xff0c;为来京就医的外省市参保人员提供便利///杭州召开平台经济健康高质量发展座谈会落实更有针对性的政策供给、提供“店小二”“保姆式”服务、建立…...

HTML img和video object-fit 属性

简介 Css中object-fit主要是应用到img标签和Video标签的&#xff0c;来控制显示缩放效果的。 首先我们存在一张图片&#xff0c;原始图片的尺寸是 1080px x 600px, 展示效果如下&#xff1a; 如果我们的css样式中的img大小设定并不能满足图片的原始大小&#xff0c;比如我们的…...

Pascal版本的 - freopen

参数 filename -- 这是包含要打开的文件的名称的字符串。 mode -- 这是包含文件访问模式的字符串。它包括 - 高级编号模式&说明1个 “r” 打开文件进行读取。该文件必须存在。 2个 “w” 创建一个用于写入的空文件。如果已存在同名文件&#xff0c;则删除其内容并将该文件…...

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 只需要有操作系统和浏览器就行&#xff0c;可以实现跨平台&#xff0c;客户端零维护&#xff0c;维护成本低&#xff0c;但是个性化能力低&#xff0c;响应速度较慢 C/S响应速度快&#xff0c;安全性强&#xff0c;一般应用于局域网中&#xff0c;因…...

硬件篇-配置

机箱->239元 机箱选用的itx迷你机箱&#xff0c;为了后期nas方便拓展选了4盘位&#xff0c;该机箱还是比较符合我的预期的&#xff0c;颇有种麻雀虽小五脏俱全的感觉&#xff0c;机箱可以安装matx主板和itx主板&#xff0c;还是比较方便的&#xff0c;机箱带三个大散热风扇&…...

网页内容 中文乱码 解决办法

原因 是因为没有网页没有设置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. 拷贝构造函数&#xff08;现代写法&#xff09;3. 析构函数4.…...

C++中的右值引用与移动构造函数

1.右值引用右值引用是 C11 引入的与 Lambda 表达式齐名的重要特性之一。它的引入解决了 C 中大量的历史遗留问题&#xff0c; 消除了诸如 std::vector、std::string 之类的额外开销&#xff0c; 也才使得函数对象容器 std::function 成为了可能。1.1左值、右值的纯右值、将亡值…...

Swift如何使用依赖注入进行解藕

Swift 中可以使用依赖注入&#xff08;Dependency Injection&#xff09;来解耦组件之间的依赖关系。依赖注入是一种设计模式&#xff0c;指的是在运行时&#xff0c;将一个组件所依赖的其他组件通过构造函数或者属性注入的方式传递给该组件。 例如&#xff0c;有两个组件 A 和…...

合宙ESP32S3-CORE开发板|保姆级|Arduino IDE|windows11|esp32S3支持库|helloword例程:Arduino 环境搭建

Arduino主页网址&#xff1a; Software | Arduino 以windows11版本为例&#xff1a; Arduino IDE最新版本为2.0.3 左边的按钮是直接下载&#xff08;免捐赠&#xff09;&#xff1a; 下载安装完成后&#xff0c;更改软件默认语言&#xff1a; 默认的库是不支持ESP32的&#…...

CMake中target_precompile_headers的使用

CMake中的target_precompile_headers命令用于添加要预编译的头文件列表&#xff0c;其格式如下&#xff1a; target_precompile_headers(<target><INTERFACE|PUBLIC|PRIVATE> [header1...][<INTERFACE|PUBLIC|PRIVATE> [header2...] ...]) # 1 target_preco…...

SpringCloud和微服务介绍

SpringCloud介绍 SpringCloud是在SpringBoot的基础上构建的,用于简化分布式系统构建的工具集。 该工具集为微服务架构中所涉及的配置管理,服务发现,智能路由,断路器,微代理和控制总线等操作提供了一种简单的开发方式。 SpringCloud中包含了多个子项目&#xff1a; Spring …...

Qt源码编译过程中配置文件中的选项说明

文章目录选项说明默认值顶级安装目录-prefix 部署目录&#xff0c;如目标设备上所示。/usr/local/Qt-$QT_VERSION-extprefix 安装目录&#xff0c;如主机上所示。SYSROOT/PREFIX-hostprefix [dir]主机上运行的生成工具的安装目录。如果未给定[dir]&#xff0c;则将使用当前构建…...

Mysql 增删改查(一) —— 查询(条件查询where、分页limits、排序order by、分组 group by)

查询 select 可以认为是四个基本操作中使用最为频繁的操作&#xff0c;然而数据量比较大的时候&#xff0c;我们不可能查询所有内容&#xff0c;我们一般会搭配其他语句进行查询&#xff1a; 假如要查询某一个字段的内容&#xff0c;可以使用 where假如要查询前几条记录&#…...

VScode 结合clangd 构建linux源代码阅读环境

1、背景介绍上一篇文章&#xff1a;VScode 结合Global构建linux源代码阅读环境 &#xff0c;介绍了在VS Code工具中通过remote-ssh远程登陆到Linux远程服务器&#xff0c;使用Global构建linux源代码阅读环境&#xff0c;对linux kernel代码进行解析&#xff0c;实现全局搜索、自…...

web应用 —— JavaScript

Web应用(acwing) 三、JavaScript 1.JS的调用方式与执行顺序 ①使用方法 HTML页面中任意位置加上<script type"module"></script>标签即可 常见使用方式&#xff1a; 直接在<script type"module"></script>标签内写JS代码。直…...

SSM整合SpringSecurity简单使用

一、SpringSecurity 1.1 什么是SpringSecurity Spring Security 的前身是 Acegi Security &#xff0c;是 Spring 项目组中用来提供安全认证服务的框架。(官网地址) Spring Security 为基于J2EE企业应用软件提供了全面安全服务。特别是使用领先的J2EE解决方案-Spring框架开发…...

椭圆曲线密码学(ECC)

一、ECC算法概述 椭圆曲线密码学&#xff08;Elliptic Curve Cryptography&#xff09;是基于椭圆曲线数学理论的公钥密码系统&#xff0c;由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA&#xff0c;ECC在相同安全强度下密钥更短&#xff08;256位ECC ≈ 3072位RSA…...

Java入门学习详细版(一)

大家好&#xff0c;Java 学习是一个系统学习的过程&#xff0c;核心原则就是“理论 实践 坚持”&#xff0c;并且需循序渐进&#xff0c;不可过于着急&#xff0c;本篇文章推出的这份详细入门学习资料将带大家从零基础开始&#xff0c;逐步掌握 Java 的核心概念和编程技能。 …...

解读《网络安全法》最新修订,把握网络安全新趋势

《网络安全法》自2017年施行以来&#xff0c;在维护网络空间安全方面发挥了重要作用。但随着网络环境的日益复杂&#xff0c;网络攻击、数据泄露等事件频发&#xff0c;现行法律已难以完全适应新的风险挑战。 2025年3月28日&#xff0c;国家网信办会同相关部门起草了《网络安全…...

打手机检测算法AI智能分析网关V4守护公共/工业/医疗等多场景安全应用

一、方案背景​ 在现代生产与生活场景中&#xff0c;如工厂高危作业区、医院手术室、公共场景等&#xff0c;人员违规打手机的行为潜藏着巨大风险。传统依靠人工巡查的监管方式&#xff0c;存在效率低、覆盖面不足、判断主观性强等问题&#xff0c;难以满足对人员打手机行为精…...

【Elasticsearch】Elasticsearch 在大数据生态圈的地位 实践经验

Elasticsearch 在大数据生态圈的地位 & 实践经验 1.Elasticsearch 的优势1.1 Elasticsearch 解决的核心问题1.1.1 传统方案的短板1.1.2 Elasticsearch 的解决方案 1.2 与大数据组件的对比优势1.3 关键优势技术支撑1.4 Elasticsearch 的竞品1.4.1 全文搜索领域1.4.2 日志分析…...

32单片机——基本定时器

STM32F103有众多的定时器&#xff0c;其中包括2个基本定时器&#xff08;TIM6和TIM7&#xff09;、4个通用定时器&#xff08;TIM2~TIM5&#xff09;、2个高级控制定时器&#xff08;TIM1和TIM8&#xff09;&#xff0c;这些定时器彼此完全独立&#xff0c;不共享任何资源 1、定…...

高分辨率图像合成归一化流扩展

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 1 摘要 我们提出了STARFlow&#xff0c;一种基于归一化流的可扩展生成模型&#xff0c;它在高分辨率图像合成方面取得了强大的性能。STARFlow的主要构建块是Transformer自回归流&#xff08;TARFlow&am…...

起重机起升机构的安全装置有哪些?

起重机起升机构的安全装置是保障吊装作业安全的关键部件&#xff0c;主要用于防止超载、失控、断绳等危险情况。以下是常见的安全装置及其功能和原理&#xff1a; 一、超载保护装置&#xff08;核心安全装置&#xff09; 1. 起重量限制器 功能&#xff1a;实时监测起升载荷&a…...

五、jmeter脚本参数化

目录 1、脚本参数化 1.1 用户定义的变量 1.1.1 添加及引用方式 1.1.2 测试得出用户定义变量的特点 1.2 用户参数 1.2.1 概念 1.2.2 位置不同效果不同 1.2.3、用户参数的勾选框 - 每次迭代更新一次 总结用户定义的变量、用户参数 1.3 csv数据文件参数化 1、脚本参数化 …...

二叉树-144.二叉树的前序遍历-力扣(LeetCode)

一、题目解析 对于递归方法的前序遍历十分简单&#xff0c;但对于一位合格的程序猿而言&#xff0c;需要掌握将递归转化为非递归的能力&#xff0c;毕竟递归调用的时候会调用大量的栈帧&#xff0c;存在栈溢出风险。 二、算法原理 递归调用本质是系统建立栈帧&#xff0c;而非…...