c/c++ 宏定义里的#和##

news2024/12/23 17:39:05

        工作中如果是c开发的话,经常会用到宏定义,而宏定义中的#和##也会时不时遇到,今天分享这两个符号的作用。

1,# -- 转换成字符串

直接看例子:

#include <stdio.h>
#include <stdlib.h>

#define VAL2STR(VAL) (#VAL) 

#define fun_call_rt(func)		\
do								\
{								\
	int ret = func;				\
	if(ret){printf("%d = %s\n", ret, #func);} \
} while (0);

int func_for_test(int value);
int main()
{
	int val = 200;
	printf("%s\n", VAL2STR(200));

	fun_call_rt(func_for_test(10));

	return 0;
}

int func_for_test(int value)
{
	if(value == 100)
	{
		return 0;
	}
	else
	{
		return -1;
	}
}

我们可以直接用gcc -E 预编译看看宏展开后是什么样的?如用命令 gcc -E test_#.c -o preprocess_test 编译后,我们看最后的代码:

其中的  VAL2STR(200) 被替换成了 ("200"),fun_call_rt(func) 中的 #func 被替换成了 "func_for_test(10)",即都被替换成了字符串,在c语言中应该称为字符数组类型。

在一些公司中类似 fun_call_rt(func) 宏几乎处处可见,在每个函数调用的地方都是这个宏括起来,一旦有错误发生,打印输出一目了然。

2, ## -- 连接两个语句为一个语句

这里所说的语句,可以是函数名,类型名,变量名,但都需要有实际意义,否则就会编译不过,看代码:

#include <stdio.h>
#include <stdlib.h>

#define NAME_JOIN(x,y) x##y

int func_for_test_1();
int main()
{
	printf("%p\n", NAME_JOIN(func_for_test, _1));
	return 0;
}

int func_for_test_1()
{
	return 10;
}

假如我改成 printf("%p\n", NAME_JOIN(func_for_test1, _1)); 在编译的时候会出现错误:

因为 NAME_JOIN(func_for_test1, _1) 只是简单的把两个短语连接为一个短语,而连接后的这个短语是否有效那就要做语法检测了,如上面执行的结果为:打印函数的地址

那如果改成这样:printf("ret = %d\n", NAME_JOIN(func_for_test, _1)()); 就是一个函数调用了,其结果就是:

 

而有一种情况这个 ## 可能不会是你想要的结果,那就是宏定义里又包含宏定义,如:

 

#include <stdio.h>
#include <stdlib.h>

#define NUMBER_1 _1
//#define NAME_JOIN(x,y) NAME_JOIN2(x,y)
#define NAME_JOIN(x,y) x##y

int func_for_test(int value);
int func_for_test_1();
int main()
{
        printf("ret = %d\n", NAME_JOIN(func_for_test, NUMBER_1)());
        return 0;
}

int func_for_test_1()
{
        return 10;
}

NAME_JOIN(func_for_test, NUMBER_1) 宏定义里又包含了宏 NUMBER_1,这样编译会出现什么问题呢?

可以看到  NUMBER_1 没有被展开,我们想要的是它被展开为 -1,即 func_for_test_1。处理办法就是再多加一个宏定义,如:

#include <stdio.h>
#include <stdlib.h>

#define NUMBER_1 _1
#define NAME_JOIN(x,y) NAME_JOIN2(x,y)
#define NAME_JOIN2(x,y) x##y

int func_for_test(int value);
int func_for_test_1();
int main()
{
        printf("ret = %d\n", NAME_JOIN(func_for_test, NUMBER_1)());
        return 0;
}

int func_for_test_1()
{
        return 10;
}

这样就能正确展开,编译成功。

 

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

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

相关文章

vue非单文件组件的使用方法

标准化开发时的嵌套&#xff1a; 在实际开发中&#xff0c;通常会创建一个 APP 组件作为根组件&#xff0c;由这个根组件去管理其它的组件&#xff0c;而 Vue 实例只需要管理这个 APP 组件就行了。 <!DOCTYPE html> <html><head><meta charset"utf…

springboot+java办公用品租赁领用管理信息系统

将系统权限按管理员和员工这两类涉及员工划分。 (a) 管理员&#xff1b;管理员使用本系统涉到的功能主要有&#xff1a;个人中心、员工管理、办公用品管理、领用申请管理、采购申请管理、物品分类管理、系统管理等功能。 (b)员工进入系统前台可以实现办公用品管理、领用申请管理…

TimerResolution.exe

TimerResolution.exe是一款常用的Windows实用程序,用于调整系统计时器的分辨率。它提供了一种简便的方法,让用户能够更精确地控制计时器的运行方式,从而改善系统的性能和响应时间。无论是进行游戏、音频处理还是其他需要精确计时的任务,TimerResolution.exe都能提供极大的帮…

【PR】来制作视频进度条吧~

【PR】来制作视频进度条吧~ 制作进度条制作分割线及标题分割线标题其他 为啥视频要有进度条~ 方便观众回看和定位&#xff1a;添加进度条可以让观众在观看视频时随时了解视频播放的进度&#xff0c;也方便观众在需要回看或者查找某一段内容时能够更加精准地定位。 提高观看体验…

当电脑回收站图标不见后,这4种方法帮你快速恢复

我们都知道&#xff0c;在电脑上删除文件时&#xff0c;这些文件多数都会先停留在回收站中。当我们后悔删除这些文件时&#xff0c;往往可以通过回收站还原&#xff0c;可是有些小伙伴却发现自己的电脑回收站不见了&#xff0c;这无疑给我们的回收站文件恢复工作带来不便&#…

NXP MCUXPresso - 操作整理

文章目录 NXP MCUXPresso - 操作整理概念如何在工程中全局搜索文本?在一个编译配置中, 如何排除一些不要的内容?END NXP MCUXPresso - 操作整理 概念 在尝试迁移 openpnp - Smoothieware project 从gcc命令行 MRI调试方式 到NXP MCUXpresso工程. 这个IDE还是蛮喜欢的, 细节…

人工智能算法|K均值聚类算法Python实现

01、算法说明 K均值聚类算法是一种简单的迭代型聚类算法&#xff0c;采用距离作为相似性指标&#xff0c;从而发现给定数据集中的K个类&#xff0c;且每个类有一个聚类中心&#xff0c;即质心&#xff0c;每个类的质心是根据类中所有值的均值得到。对于给定的一个包含n个d维数据…

Word怎么删除空白页?分享5个基础方法!

案例&#xff1a;Word怎么删除空白页 【我最近在用word写文章&#xff0c;但经常都会遇到的一个问题就是总是会有空白页&#xff0c;使用word时怎么删除空白页呢&#xff1f;请大家给我支支招吧&#xff01;】 在使用Microsoft Word编辑文档时&#xff0c;有时会出现空白页&a…

Stimulsoft 报表开发工具支持设置水印啦!一起来看~

Stimulsoft Reports是一款报告编写器&#xff0c;主要用于在桌面和Web上从头开始创建任何复杂的报告。可以在大多数平台上轻松实现部署&#xff0c;如ASP.NET, WinForms, .NET Core, JavaScript, WPF, Angular, Blazor, PHP, Java等&#xff0c;在你的应用程序中嵌入报告设计器…

AI智能机器人的语音消息使用方式

如何在没有资金扩大营销的情况下增加收入&#xff0c;这是不是有点像先有蛋还是先有鸡的问题&#xff1f;如果没有足够的收入来源&#xff0c;小型企业很难对新客源扩展营销和传播。有关系统问题欢迎和博主一起交流。 机器人的语音消息是不是给百姓造成了生活上的影响&#xf…

Redis内存优化——Stream类型介绍及底层原理详解

系列文章目录 Redis内存优化——String类型介绍及底层原理详解 Redis内存优化——Hash类型介绍及底层原理详解 Redis内存优化——List类型介绍及底层原理详解 Redis内存优化——Set类型介绍及底层原理详解 Redis内存优化——ZSet类型介绍及底层原理详解 Redis内存优化——Stre…

4 个无质量损失的免费在线图像压缩器

本文内容&#xff1a;最佳在线图像优化器&#xff0c;无质量损失&#xff0c;可让您压缩 JPG、PNG 和 GIF 文件。 在线图像优化器工具可帮助您压缩图像而不会降低质量。并给出图像可以压缩多少的想法。 经过测试和比较的没有质量损失的最佳在线图像优化器 4 个无质量损失的免…

网管必备技巧:如何跟踪IP地址

作为网管员&#xff0c;在我们解决Windows 操作系统的DHCP故障时&#xff0c;有时要找出某个地址范围内有哪些地址没有被使用。方法&#xff1a;打开命令提示窗口&#xff0c;在For…in…Do循环中调用ping命令。 例如&#xff0c;为了找出在地址范围192.168.1.1 到 192.168.1.1…

左耳朵耗子

晚上回来后&#xff0c;到coolshell上看文章。 程序员是一件非常累的工作&#xff0c;在我看到稚晖君做出那么多优秀的产品&#xff0c;我是很惊叹的&#xff0c;因为我知道那需要付出非常非常多的时间和精力&#xff0c;当大家都在夸赞的时候&#xff0c;我也能发现稚晖君发梢…

GitHub Copilot:神一样的代码助手

我肝肯定&#xff0c;很多很多小伙伴还不了解 Copilot 是什么&#xff0c;尤其是初学计算机的小伙伴&#xff0c;我这里普及一下吧&#xff01; GitHub Copilot 是一个基于 AI 的代码自动完成工具&#xff0c;由 GitHub 和 OpenAI 共同开发。 GitHub 和 OpenAI 想必大家都很清楚…

《计算机网络——自顶向下编程》精炼——3.4.4

人生的旅途,前途很远,也很暗,名言警句励志。然而不要怕,不怕的人的面前才有路。——鲁迅 文章目录 选择重传&#xff08;SR&#xff09; 选择重传&#xff08;SR&#xff09; 选择重传协议是另一种流水线rdt协议。与GBN协议最大的区别是当发送方收到一个失序分组时&#xff0c…

微信小程序实现人脸识别(戴面具效果)

节前准备:文档: xr-frame 模型链接 (注明&#xff1a;来源于微信开放文档) 基础要点: 1.ar-system"modes:Face;camera:Front" ar-system 表示ar系统&#xff0c;camera表示相机(默认为后置Back&#xff0c;前置为Front) modes 表示模式,目前支持平面识…

DSBC176 3BSE019216R1​有综合保护器、电流表、电压表等器件​

​ DSBC176 3BSE019216R1 有综合保护器、电流表、电压表等器件 另一个方法是先对数组排序&#xff0c;然后取中间元素即可&#xff0c;因为如果某个元素的个数超过一半&#xff0c;那么数组排序后该元素必定占据数组的中间位置。 求数组中元素的最短距离 给定一个含有n个元素…

大数据分析案例-基于GBDT梯度提升决策树算法构建数据科学岗位薪资预测模型

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…

中小企业CRM如何选型?

中小企业CRM如何选型&#xff1f;这就来分享一下&#xff01; 中小企业客户关系管理系统(CRM)的选型需要考虑多个方面&#xff0c;包括成本&#xff0c;功能&#xff0c;易用性&#xff0c;扩展性和安全性。 预算&#xff1a;中小企业的预算通常有限&#xff0c;因此成本是选…