C语言的预处理器无法先展开宏再拼接符号?可以!

news2025/1/20 10:59:29

背景

最近接到一个需求,要实现一个脚本,能提取.h文件里定义的所有全局变量的值,这些全局变量都是结构体变量,名字是结构体类型名场景后缀——每个.h对应的场景都是唯一的,所以.h内所有变量名的后缀一致。

我的解决方案

我想到的解决方案是,写一个打桩的.c文件,里面实现一个accessor函数,根据参数结构体名场景名返回对应的变量值。结构体名种类固定,可以写死,但场景名无限多,必须动态传入,于是想到使用gcc的-D选项。该选项可以实现#define语句的效果,即定义一个,场景就可以通过宏展开来传递了,示例代码如下:

int luma_cinema = 3;
int luma_theater = 4;

#define PASTE(param_name, scene_name) param_name ## _ ## scene_name

int main() {
    //return luma_##SCENE; //符号拼接只能在#define语句内出现!
    return PASTE(luma, SCENE);
}

脚本通过如下命令行传递场景名:

gcc -DSCENE=cinema test_sharp.c

我的方案失败了

上面的代码编译不过:

test_sharp.c: In function ‘main’:
test_sharp.c:8:18: error: ‘luma_SCENE’ undeclared (first use in this function); did you mean ‘SCENE’?
     return PASTE(luma, SCENE);
                  ^
test_sharp.c:4:39: note: in definition of macro ‘PASTE’
 #define PASTE(param_name, scene_name) param_name ## _ ## scene_name
                                       ^~~~~~~~~~
test_sharp.c:8:18: note: each undeclared identifier is reported only once for each function it appears in
     return PASTE(luma, SCENE);
                  ^
test_sharp.c:4:39: note: in definition of macro ‘PASTE’
 #define PASTE(param_name, scene_name) param_name ## _ ## scene_name
                                       ^~~~~~~~~~

分析

查看cpp命令(C preprocessor)的输出

查看cpp的输出

cpp -DSCENE=cinema test_sharp.c

发现只执行了符号拼接,没有执行宏展开

# 1 "test_sharp.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "test_sharp.c"
int luma_cinema = 3;
int luma_theater = 4;



int main() {

    return luma_SCENE;
}

自己的理解

当展开PASTE宏时,cpp只会执行一次展开,即宏函数的展开,不会再对宏函数的参数进行展开了。

要想先展开宏定义,再展开宏拼接,需要两次展开,怎么实现两次展开呢?

查看cpp的官方文档

查看官方文档,发现这行话:
宏先展开再拼接
看样子就是定义2个宏函数,类似于二级指针的意思。

解决问题

修改我的原始代码:

int luma_cinema = 3;
int luma_theater = 4;

#define _PASTE(param_name, scene_name) param_name ## _ ## scene_name
#define PASTE(param_name, scene_name) _PASTE(param_name, scene_name)

int main() {
    //return luma_##SCENE;
    return PASTE(luma, SCENE);
}

这次gcc编译通过,运行效果:

$ gcc -DSCENE=cinema test_sharp.c
$ ./a.out
$ echo $?
3

a.out程序退出时返回3,说明符合代码预期。

查看cpp的输出,也符合预期:

# 1 "test_sharp.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "test_sharp.c"
int luma_cinema = 3;
int luma_theater = 4;




int main() {

    return luma_cinema;
}

后记

昨天这个问题逼得我无奈使用sed动态替换打桩.c里的场景名,非常笨拙,并熬夜看了一部分GNU m4的资料。没想到预处理器本身就支持,以后有时间要好好研究预处理器。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/84615.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

线段树详解(包含加法线段树、乘法线段树及区间根号线段树,简单易懂)

同步发表于洛谷梦回江南 这一篇文章我们将对线段树中的常规操作进行详细的讨论。 以下所提到的复杂度如无特殊说明均为时间复杂度。log⁡\loglog 的底数均为 222。 不开 long long 见祖宗&#xff01; 文章目录第一部 普通线段树一、引入二、优化方案三、懒标记&#xff08;l…

[附源码]Python计算机毕业设计电影网站系统Django(程序+LW)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程 项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等…

什么是编程的设计模式,史上最全面Java设计模式总结,看完再也不会忘记

文章目录**9.1 工厂方法模式与抽象工厂模式对比#****9.2 简单工厂模式与单例模式对比#****9.3 简单工厂模式与建造者模式对比#****10.1 装饰器模式与代理模式对比#****10.2 装饰器模式与门面模式对比#****10.3 装饰器模式与适配器模式对比#****10.4 适配器模式与代理模式…

人事管理系统--低代码课程的教学实验/实训教学 (①招聘管理)

人事管理系统是信息系统课程中最为常见的教学场景&#xff0c;对于非计算机专业的学生来说&#xff0c;如何使用低代码&#xff0c;甚至是零代码的方式搭建该系统呢&#xff1f;简道云「人事OA管理」应用包含招聘管理、人员入离职管理、考勤管理、会议室预约、物资进销存管理等…

#3文献学习总结--边缘计算资源分配与任务调度优化

文献&#xff1a;“边缘计算资源分配与任务调度优化综述 ” 1、系统模型“云-边-端” 第 1 层是物联网层&#xff0c;传感器、处理器根据应用需求感知、测量和收集原始数据&#xff0c;在本地处理大量数据或将其上传至计算节点。 第 2 层是边缘计算层&#xff0c;位于互联网边…

rollup打包vue组件

rollup安装与使用 npm i rollup -g # 全局安装 npm i rollup -D # 项目本地安装rollup配置 import vue from rollup-plugin-vue import typescript from rollup-plugin-typescript2 import postcss from rollup-plugin-postcss; import cssnano from cssnano i…

2022华为全球校园AI算法精英赛:季军方案!

Datawhale干货 作者&#xff1a;鲤鱼&#xff0c;西安交通大学&#xff0c;人工智能学院笔者鲤鱼&#xff0c;是西安交通大学人工智能学院的一名研究生&#xff0c;在2022华为全球校园AI算法精英赛的赛道二取得了季军的成绩。初赛阶段一直名列A榜的榜首&#xff0c;复赛前几天也…

zabbix6.0安装教程(二):Zabbix6.0安装最佳实践

zabbix6.0安装教程&#xff08;二&#xff09;&#xff1a;Zabbix6.0安装最佳实践 目录概述一、Access control1.Zabbix agent 的安全用户2.UTF-8 编码二、Zabbix Security Advisories and CVE database1.为 Zabbix 前端设置 SSL三、Web server hardening1.在 URL 的根目录上启…

[附源码]Python计算机毕业设计SSM基于的开放式实验室预约系统(程序+LW)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

人家这才叫软件测试工程师,你那只是混口饭吃

前些天和大学室友小聚了一下&#xff0c;喝酒喝大发了&#xff0c;谈天谈地谈人生理想&#xff0c;也谈到了我们各自的发展&#xff0c;感触颇多。曾经找工作我迷茫过、徘徊不&#xff0c;毕业那会我屡屡面试失败&#xff0c;处处碰壁&#xff1b;工作两年后我一度想要升职加薪…

[附源码]Python计算机毕业设计SSM基于的二手车商城(程序+LW)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

第五款!美创数据水印溯源系统通过中国信通院数据安全能力评测

近期&#xff0c;中国信息通信研究院安全研究所发布“数据安全产品能力验证计划”第六期通过企业名单。美创科技数据水印溯源系统顺利通过测试&#xff0c;成为美创第五款通过权威检验测评的数据安全产品&#xff01; 此前&#xff0c;中国信息通信研究院安全所开展数据安全类产…

分布式系统中的数据复制

什么是数据复制 数据复制是制作数据的多个副本并将其存储在不同位置的过程&#xff0c;用于备份目的、容错和提高它们在网络中的整体可访问性。与数据镜像类似&#xff0c;数据复制可以应用于单个计算机和服务器。复制的数据可以存储在同一系统、现场和非现场主机以及基于云的…

FT 在图形渲染中的应用:基于 FFT 的海浪模拟

接上文&#xff1a;FT 在图像处理中的应用 五、一个大型案例&#xff1a;基于 FFT 的海浪模拟 前置&#xff1a;​​​​​ 傅里叶级数与傅里叶变换离散傅里叶变换(DFT)​​​​​​​​FT 在图像处理中的应用​5.1 FFT 海洋公式&#xff1a;二维 IDFT https://tore.tuhh.de…

Abz-G-F(4NO2)-P-OH, 67482-93-3

Fluorogenic (FRET) substrate for angiotensin I-converting enzyme (ACE). Enzymatic cleavage of Abz-Gly-Nph-Pro yields Abz-Gly-OH emitting at 420 nm. 血管紧张素I转换酶&#xff08;ACE&#xff0c;ACE2&#xff09;底物 血管紧张素i转换酶(ACE)的荧光底物。Abz-Gly-N…

docker 报错 No space left on device

问题&#xff1a; 在 Linux 环境上使用 docker 命令 <docker pull 镜像> 拉取镜像的时遇到了 No space left on device 的问题。 排查过程&#xff1a; 初步分析可能是存储镜像的路径磁盘满了。 但是使用 df -h 命令之后&#xff0c;发现磁盘还有空间。于是猜测应该是…

【Linux】Linux软件包管理器yum

希望你今天有一个好心情 文章目录一、(客户端&&服务器) (软件包&&软件包管理器yum) (利益链&&逻辑链)1.客户端&&服务器2.软件包&&软件包管理器3.一条利益链一条逻辑链二、Linux下包管理器yum的使用(root身份或sudo提权进行搜索list…

【安全】免密登陆SQLSERVER 之 Token 窃取

先"灌肠" 往往在高版本系统 或者 在强密码的等等 特殊情况下我们无法获得 明文密码。那么我们该如何在没有明文密码及有windows哈希的情况下登陆 SQLSERVER呢(当然我并没有sa等任何账号); 默认安装点击登陆名 发现有好几个可以登陆的用户在users 组里都可以登陆 (基本…

WLAN二层旁挂组网与三层旁挂组网

第一部分&#xff1a;关于底层逻辑问题 1、WLAN二层组网与三层组网到底是指哪里是二层哪里是三层&#xff0c;两者有什么区别&#xff1f; WLAN的二层组网与三层组网指的是AP与AC之间建立的Capwap隧道是二层的还是三层的&#xff0c;以此来区分是二层组网还是三层组网。注意&…

使用微信部署ChatGPT

使用微信部署ChatGPT 一、介绍 最近ChatGPT爆火&#xff0c;网上出现了很多ChatGPT项目&#xff0c;有部署到微信的&#xff0c;有部署到QQ机器人的&#xff0c;今天介绍一种部署到微信的方法。 此项目参考github上https://github.com/869413421/wechatbot项目&#xff0c;需…