C,C++宏中#和##

C/C++中##与#的使用 在酷壳上面看到了这么一道个程序,很有意思。 引自酷壳: 下面这段程序的输出结果是: 1 2 3 4 5 6 7 8 9 10 11 #include #define f(a,b) a##b #define g(a)   #a #define h(a) g(a)   int main() { 阅读详情

文中__FILE__与示例1可以参见《使用ANSI C and Microsoft C++中常用的预定义宏》

宏中的#的功能是将其后面的宏参数进行字符串化操作(Stringizing operator),简单说就是在它引用的宏变量的左右各加上一个双引号。

如定义好#define STRING(x) #x之后,下面二条语句就等价。

       char *pChar = "hello";

       char *pChar = STRING(hello);

还有一个#@是加单引号(Charizing Operator)

#define makechar(x)  #@x

       char ch = makechar(b);与char ch = 'b';等价。

 

但有小问题要注意,宏中遇到#或##时就不会再展开宏中嵌套的宏了。什么意思了?比如使用char *pChar =STRING(__FILE__);虽然__FILE__本身也是一个宏,但编译器不会展开它,所以pChar将指向"__FILE__"而不是你要想的形如"D:\XXX.cpp"的源文件名称。因此要加一个中间转换宏,先将__FILE__解析成"D:\XXX.cpp"字符串。

定义如下所示二个宏:

#define _STRING(x) #x

#define STRING(x) _STRING(x)

再调用下面语句将输出带""的源文件路径

       char* pChar = STRING(__FILE__);

       printf("%s %s\n", pChar, __FILE__);

可以比较下STRING(__FILE__)与__FILE__的不同,前将带双引号,后一个没有双引号。

 

再讲下##的功能,它可以拼接符号(Token-pasting operator)。

MSDN上有个例子:

#define paster( n ) printf( "token"#n" = %d\n", token##n )

int token9 = 100;

再调用  paster(9);宏展开后token##n直接合并变成了token9。整个语句变成了

printf( "token""9"" = %d", token9 );

在C语言中字符串中的二个相连的双引号会被自动忽略,于是上句等同于

printf("token9 = %d", token9);。

即输出token9 = 100

 

 

有了上面的基础后再来看示例1

#define WIDEN2(x) L ## x

#define WIDEN(x) WIDEN2(x)

#define __WFILE__ WIDEN(__FILE__)

wchar_t *pwsz = __WFILE__;

第一个宏中的L是将ANSI字符串转化成unicode字符串。如:wchar_t *pStr = L"hello";

再来看wchar_t *pwsz = __WFILE__;

__WFILE__被首先展开成WIDEN(__FILE__),再展开成WIDEN2("__FILE__表示的字符串"),再拼接成 L"__FILE__表示的字符串" 即L"D:\XXX.cpp" 从而得到unicode字符串并取字符串地址赋值给pwsz指针。

 

在VC中_T(),TEXT ()也是用的这种技术。

在tchar.h头文件中可以找到:

#define _T(x)       __T(x)

#define __T(x)      L ## x

在winnt.h头文件中可以找到

#define TEXT(quote) __TEXT(quote)   // r_winnt

#define __TEXT(quote) L##quote      // r_winnt

因此不难理解为什么第三条语句会出错error C2065: 'LszText' : undeclared identifier

       wprintf(TEXT("%s %s\n"), _T("hello"), TEXT("hello"));

       char szText[] = "hello";

       wprintf(TEXT("%s %s\n"), _T(szText), TEXT(szText));

而将"hello"定义成宏后就能正确运行。

#define SZTEXT "hello"

       wprintf(TEXT("%s %s\n"), _T(SZTEXT), TEXT(SZTEXT));

注:由于VC6.0默认是ANSI编码,因此要先设置成unicode编码,在project菜单中选择Setting,再在C/C++标签对话框中的Category中选择Preprocessor。再地Preprocessor definitions编辑框中将_MBCS去掉,加上_UNICODE,UNICODE。

原文引用:http://www.cnblogs.com/morewindows/archive/2011/08/18/2144112.html;

【C/C++】Debug宏,#和##的介绍及实例 一、C语言中引入了几个用于Debug的内置宏,其作用为输出宏所对应的信息。 返回char*类型的日期 __DATE__ 返回char*类型的时间 __TIME__ 返回int类型的行号 __LINE__ 返回char*类型文件名及所在路径 __FILE__ 返回该宏所在最内层函数名,非标准内置宏,MSVC/Clang/G++使用小写的func __func__ __FUNC__ 实例代码如下: #include <iostream> usin... 阅读详情

相关推荐

C/C++ 宏中“##”与“#”的用法

是两个特殊的预处理操作符,用于在宏展开时对参数进行字符串化和符号连接。:将两个符号(Token)拼接为一个新的符号。:将宏参数转换为字符串常量(即添加双引号)。在 C/C++ 宏中,符号1 ## 符号2。

qq_36812406的博客 1578

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

其中的 VAL2STR(200) 被替换成了 ("200"),fun_call_rt(func) 中的 #func 被替换成了 "func_for_test(10)",即都被替换成了字符串,在c语言中应该称为字符数组类型。因为 NAME_JOIN(func_for_test1, _1) 只是简单的把两个短语连接为一个短语,而连接后的这个短语是否有效那就要做语法检测了,如上面执行的结果为:打印函数的地址。我们可以直接用gcc -E 预编译看看宏展开后是什么样的?2, ## -- 连接两个语句为一个语句。

tianyexing2008的博客 2771

C/C++/中宏特殊字符的含义及用法总结(“#”、“##”、"#@"、“\”等等)

在C/C++中,宏定义是由define完成的,宏定义中有几种常见的特殊字符需要我们了解,常用的特殊字符有以下几种: #:在宏展开的时候会将#后面的参数替换成字符串; 字符串化 ##:将前后两个的单词拼接在一起; 连接化 #@:将值序列变为一个字符; 字符化 \:将两行连接起来。行连接化 我们可以使用这些特殊的字符做一些简单的测试例子: 1.# 测试 测试代码如下: #i...

尘海折柳的博客 8403

C/C++ 的宏中#和##的作用和展开

C/C++ 的宏中,#的功能是将其后面的宏参数进行字符串化操作,简单说就是在对它所引用的宏变量通过替换后在其左右各加上一个双引号。 ##连接符号由两个井号组成,其功能是在带参数的宏定义中将两个子串联接起来,从而形成一个新的子串。但它不可以是第一个或者最后一个子串。 凡是宏定义里有用#或##的地方宏参数是不会再展开,例如_STRI(INT_MAX)中的INT_MAX就不会被展开为214748364...

aflyeaglenku的博客(QQ1010316426) 9050

手把手教你用6轴IMU跑通LIO-SAM:参数配置与代码修改保姆级教程

本文提供了一套完整的6轴IMU适配LIO-SAM的解决方案,包括参数配置与代码修改的详细步骤。从理解6轴与9轴IMU的关键差异入手,逐步指导如何调整核心配置文件params.yaml、重构utility.h关键函数、优化mapOptimization.cpp的位姿融合逻辑,并给出编译验证与性能调优建议,帮助开发者快速实现6轴IMU在LIO-SAM中的稳定运行。

weixin_28717807的博客 357

CentOS7下Ollama部署全攻略:从安装到自定义端口配置(附国内加速技巧)

本文详细介绍了在CentOS7系统上部署Ollama的完整流程,包括环境准备、模型下载优化、服务化部署及端口配置等关键步骤。特别针对国内网络环境提供了加速安装方案和镜像源配置技巧,帮助开发者快速搭建稳定的本地AI运行环境。

mmm90的博客 289

C/C++中##和#宏

在c语言/c++中,宏(Macro)是属于编译时期(而非运行时期)的概念,采用关键字define进行定义。它只是一种简单的字符串替换,根据是否带参数分为无参和带参。 它的作用还是很大的,比如提高可移植性,可读性,方便性等等,常见就是替换变量,防止重复包含头文件等 #define MAX 10 #ifndef __HEAD_H__ #define __HEAD_H__

xy913741894的博客 478

K8s入门教程(一)

本教程提供了Kubernetes(K8s)的入门指南,涵盖了从基础概念到实战操作的全面内容。首先介绍了Kubernetes的定义和核心功能,如自动化部署、弹性伸缩、自我修复等。接着,详细讲解了如何在macOS上安装Minikube和kubectl工具,以及如何使用这些工具创建和管理Pod、Deployment和Service等核心资源。教程还包括了实战案例,如部署Nginx应用,并介绍了高级特性如滚动更新和自动伸缩。最后,提供了常见问题的解决方案,帮助用户快速上手和解决实际使用中的问题。

2401_82505179的博客 1689

C/C++ 宏中#和##

C/C++ 宏中#和##

old-windbell 521

网络虚拟化介绍(OVS、DVS)

网络虚拟化概念网络虚拟化就是把网络层的一些功能从硬件中剥离出来,建立新的网络虚拟层;该虚拟层可以接管网络服务和配置,实现网络服务与物理层的解耦,打破物理资源限制;通过网络虚拟层能够在一个物理网络上模拟出多个逻辑网络,并且多用户在逻辑网络上相互隔离,保证网络安全网络虚拟化的特点隔离性:不同租户的流量相互之间不能互访;但是IP/MAC地址都可以独立规划可移动性:虚拟机可以跨二层/三层迁移,甚至可以跨广域网迁移(迁移前后虚拟机Vlan和IP地址都不会发生变化)可扩展性:逻辑网络的规模和数量可扩展。

m0_49864110的博客 1万+

带你一分钟了解电感与磁珠的区别

在电路设计中会经常使用到电感和磁珠,虽然在电路中的作用有所不同,但它们都属于磁性电子元器件,本文简单介绍下电感和磁珠的区别电感和磁珠电感和磁珠的结构主要由磁性材料金属线圈和外壳组成,具体结构如下图所示:电感磁珠结构图电感其实是金属线圈缠绕在磁芯上,而磁珠是在内部折叠后外围包裹着铁氧体磁性材料。电感器(Inductor)又称扼流器、电抗器、动态电抗器是储能器件,能够把电能转化为磁能而存储起来的元件。磁珠则是能量转换(消耗)器件,将流过他的高频信号以热能的形式消耗掉。

攻城狮鹏哥 1410

[c、c++]宏中"#"和"##"的用法(zz)

[c、c++]宏中"#"和"##"的用法(zz) 宏中"#"和"##"的用法 一、一般用法 我们使用#把宏参数变为一个字符串,用##把两个宏参数贴合在一起. 用法: #include<cstdio> #include<climits> using namespace std; #define STR(s) #s #d...

diaoqu4574的博客 108

别再被systemd-resolved坑了!银河麒麟V10下用Bind9搭建内网DNS的完整避坑指南

本文详细介绍了在银河麒麟V10和Ubuntu系统下部署Bind9 DNS服务器时,如何解决与systemd-resolved的端口冲突问题。提供了五种专业级解决方案,包括彻底禁用systemd-resolved、智能端口转发等,并特别针对银河麒麟V10的安全加固需求给出了配置建议和诊断工具,帮助用户高效搭建内网DNS服务。

weixin_30342209的博客 655

c/c++ 宏中"#"和"##"的用法

c/c++ 宏中"#"和"##"的用法 2007年05月14日 星期一 上午 10:19 一、一般用法 我们使用#把宏参数变为一个字符串,用##把两个宏参数贴合在一起. 用法: #i nclude<cstdio> #i nclude<climits> using namespace std; #define STR(s) ...

weixin_34177064的博客 84

《YOLOv12魔术师专栏》专栏介绍 & 专栏目录

《YOLOv12魔术师专栏》专栏介绍 & 专栏目录

①答疑群聊服务;②YOLO大模型知识问答系统;③计算机视觉论文生成智能体; 5059

CRC_16---ModBus 计算方法及代码实现

1、 CRC寄存器初始值为 0xFFFF;即16个字节全为1; 2、 CRC-16 / ModBus的多项式0xA001H (1010 0000 0000 0001B) ; ‘H’表示16进制数,‘B’表示二进制数。 计算步骤为: (1).预置 16 位寄存器为十六进制 0xFFFF(即全为 1) ,称此寄存器为 CRC 寄存器; (2).把第一个 8 位数据与 16 位 CRC 寄存器的低位相异或,把结果放于 CRC 寄存器; (3).检测相异或后的CRC寄存器的最低位,若最低位为1,CRC寄存器

1万+

[zz]c/c++ 宏中"#"和"##"的用法

c/c++ 宏中"#"和"##"的用法2007年05月14日 星期一 上午 10:19一、一般用法我们使用#把宏参数变为一个字符串,用##把两个宏参数贴合在一起.用法:#i nclude<cstdio>#i nclude<climits>using namespace std; #define STR(s) #s#define CONS(a,b) int(a#...

weixin_30374009的博客 103

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

[c、c++]宏中"#"和"##"的用法

转载自:https://blog.youkuaiyun.com/blackbillow/article/details/3850587 宏中"#"和"##"的用法 一、一般用法 我们使用#把宏参数变为一个字符串,用##把两个宏参数贴合在一起. 用法: #include<cstdio> #include<climits> using namespace std; #define ST...

ayang1986的专栏 670

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

C/C++中#和##的宏以及进行“花里胡哨“的命名及其应用

最近依然在嵌入式遨游,以及加深对free rt os 源码以及内核的理解。以及为了解决学习工作中分布式设备的命名问题。于是就想到了#和##这两个宏。

昊月光华的博客 1020

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

C/C++中宏 #和 ##的讲解

文中__FILE__与示例1可以参见《使用ANSI C and Microsoft C++中常用的预定义宏》 宏中的#的功能是将其后面的宏参数进行字符串化操作(Stringizing operator),简单说就是在它引用的宏变量的左右各加上一个双引号。 如定义好#define STRING(x) #x之后,下面二条语句就等价。        char *pChar = "hello";

611

C/C++中宏#和##以及@#的作用

define宏定义中的#,##,@#及\符号(ZT) 1、# (stringizing)字符串化操作符。其作用是:将宏定义中的传入参数名转换成用一对双引号括起来参数名字符串。其只能用于有传入参数的宏定义中,且必须置于宏定义体中的参数名前。 如: #define example(instr) printf("the input string is:\t%s\n",#instr) #defin

C语言是最好的编程语言 1549

C/C++宏中 ##和#的用法

c语言中,##表示把两个宏参数贴合在一起,而单个#的功能是将其后面的宏参数进行字符串化操作。 弄两行代码记录一下: 1、“##” #define TEST1(a,b) a##b int a = TEST1(1,1);//不报错 cout &lt;&lt; a;//输出11 std::string = TEST1(1,1);//报错:不存在从“int”转换到“std::base_string&lt...

qq_28105601的博客 373
上一篇: C++对参数直接赋值
下一篇: VC 如何使程序运行后自己删除自己
CHF_VIP
博客等级 码龄14年 2粉丝 12原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值