C++预处理器中的#和##运算符

c++ map用法_C语言中"##"的独特用法 来自公众号:裸机思维C语言中一个重要的内容,就是##的用法,可能绝大部分 C 程序员都不知道"##"隐藏用法,下面就来给大家讲讲。一、##的“表”用法想必很多人都知道"##"的用法——它本质上是一个“胶水运算”(连接字符串的作用),用于把参数宏中的“形参”与其它没有天然分割的内容粘连在一起,例如:#define def_u32_array(__name, __size) u... 阅读详情

在C/C++预处理中,## 和 # 是两个不同的运算符,它们有不同的作用:

  1. # 运算符(字符串化运算符):

    • 将宏参数转换为字符串字面量
    • 示例:#define STR(x) #x 会把参数x转换为字符串
    • 使用:STR(hello) 会被替换为 "hello"
  2. ## 运算符(标记连接运算符):

    • 将两个标记连接成一个新的标记
    • 示例:#define CONCAT(a,b) a##b
    • 使用:CONCAT(var,1) 会被替换为 var1

代码:

#define concat(a, b) a##b
int a = 10, b = 20;
cout << "concat(a, b) = " << concat(a, b) << endl;

这段代码会报错"未定义标识符’ab’",因为:

  1. concat(a, b) 被替换为 a##b,然后变成 ab
  2. 但程序中并没有定义名为 ab 的变量

要使这段代码正常工作,可以改为:

#define concat(a, b) a##b
int xy = 100;  // 定义一个xy变量
cout << "concat(x, y) = " << concat(x, y) << endl;  // 这会输出xy的值

或者更实用的例子:

#define VAR_NAME(n) var##n
int VAR_NAME(1) = 10;  // 这会创建变量var1
int VAR_NAME(2) = 20;  // 这会创建变量var2

##更详细的解释

在C++预处理器中,##是标记粘贴运算符,主要作用是将两个标识符在预处理阶段组合成新的标识符。它的核心价值体现在以下场景:


典型应用场景

  1. 批量生成相似代码:
#define CREATE_VAR(type, name) type var_##name
CREATE_VAR(int, count);    // 展开为 int var_count
CREATE_VAR(float, total);  // 展开为 float var_total
  1. 动态生成函数名:
#define REGISTER_HANDLER(type) void handle_##type()
REGISTER_HANDLER(error);  // 生成 handle_error()
REGISTER_HANDLER(input);  // 生成 handle_input()
  1. 平台兼容代码:
#if defined(WIN32)
    #define DLL_EXPORT __declspec(dllexport)
#else
    #define DLL_EXPORT
#endif

#define MAKE_API(name) DLL_EXPORT void name##_api()
MAKE_API(network);  // 根据平台生成不同修饰的函数

示例解析

#define concat(a, b) a##b
int xy = 30;
cout << concat(x, y); // 预处理阶段将x和y合并为xy
为什么不直接写xy?
  1. 动态生成:当需要根据参数生成不同变量名时
for(int i=1; i<4; ++i){
    concat(var, i) = i*10; // 生成var1,var2,var3
}
// 等效于:
var1 = 10;
var2 = 20;
var3 = 30;
  1. 模板化代码:
#define CREATE_GETTER(field) \
    int get_##field() { return this->##field; }

class Person {
    int age;
    string name;
};
CREATE_GETTER(age)   // 生成 get_age()
CREATE_GETTER(name)  // 生成 get_name()

关键区别

直接使用xy使用##宏
静态已知的标识符动态生成的标识符
适用于固定名称适用于模式化名称
人工维护每个名称自动批量生成名称
代码直观易读增加一定抽象性

当需要处理大量相似标识符时(如生成系列变量/函数),##能显著减少重复代码,提高开发效率。但在简单场景(如你的示例)中使用确实显得多余

总结:

  • # 用于创建字符串
  • ## 用于连接标识符
  • 使用##时要确保连接后的标识符是已定义的
C++详解 | #define预处理器 文章目录一、预处理器二、语法三、原理三、参数宏四、类型宏五、#和##运算符 一、预处理器 预处理器是一些指令,指示编译器在实际编译之前所需完成的预处理。 所有的预处理器指令都是以井号(#)开头,只有空格字符可以出现在预处理指令之前。预处理指令不是 C++ 语句,所以它们不会以分号(;)结尾。 二、语法 #define 预处理指令用于创建符号常量。该符号常量通常称为宏,指令的一般形式是: #define marco-name replace-text 三、原理 考虑以下代码: #include<io 阅读详情

相关推荐

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

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

尘海折柳的博客 8402

C语言中"##"的独特用法

关注、星标公众号,不错过精彩内容作者:傻孩子转自:裸机思维市面上有很多比较火的编程语言,比如Python、 JAVA、 Go等,你可能觉得C语言很古老、很落后。如果你有这种想法,那可能你...

strongerHuang 1万+

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

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

qq_36812406的博客 1578

C++中的##、#符号含义

在C++中,## 和 # 是两个不同的预处理符号。这些符号都是在C++的预处理阶段使用的,用于在代码编译之前对文本进行操作。

记录值得记录的东西 5803

什么?你还不知道什么是C++ 预处理器?看这一篇就够了~

求求给个关注

阿玥的小博客 729

Cadence学习之路(六)元器件封装绘制

使用Allegro PCB Designer绘制元器件封装

qq_46757048的博客 1万+

C中宏定义#和##

C中宏定义#和##

phmatthaus的专栏 840

最新版Node.js下载安装及环境配置教程(非常详细)

选择对应你系统的Node.js版本。

DN金猿的博客 12万+

宏 #和# #的区别

在C和C++语言中,#和##都是预处理器(preprocessor)指令中使用的运算符,用于宏(Macro)的定义和展开。

ZZU_LGY 385

产品经理如何运用AI提升工作效率

AI技术的应用为产品经理的工作流程带来了显著的效率提升。从需求收集到产品上线,AI可以在多个阶段提供智能化支持,帮助产品经理更好地理解用户需求、优化产品设计、提高开发和测试效率。在未来,随着AI技术的不断发展,产品经理将能够更加高效地管理产品生命周期,为用户提供更优质的产品体验。应用 | AI + 千行百业欢迎关注我的后续博文,我将分享更多关于人工智能、自然语言处理和计算机视觉的精彩内容。

不想宅的冷同学 1336

OpenPose 论文理解

OpenPose: Real-time multi-person keypoint detection library for body, face, hands, and foot estimation paper: Realtime Multi-Person 2D Pose Estimation using Part Affinity Fields link: OpenPose paper...

JustForYou的博客 2万+

C++ 预处理器

宏描述__LINE__这会在程序编译时包含当前行号。__FILE__这会在程序编译时包含当前文件名。__DATE__这会包含一个形式为 month/day/year 的字符串,它表示把源文件转换为目标代码的日期。__TIME__这会包含一个形式为 hour:minute:second 的字符串,它表示程序被编译的时间。

weixin_71470897的博客 689

电力工程师必看:GOOSE/SV/MMS三协议在智能变电站中的分工与联动实例

本文深入解析了智能变电站中GOOSE、SV、MMS三大核心通信协议的分工与协同机制。GOOSE协议作为过程层的“闪电信使”,负责毫秒级传输跳闸命令等事件信息;SV协议则传输精确同步的电流电压采样值流;而MMS协议作为站控层的“管理语言”,实现设备监控与数据管理。三者基于IEC 61850标准,在过程层、间隔层和站控层之间高效联动,共同构建了智能变电站稳定可靠的通信骨架。

jj890的博客 364

#和##操作符使用分析

#运算符 (1)#运算符用于在预处理期将宏参数转换为字符串 (2)#的转换作用是在预处理器完成的,因此只在宏定义中有效 (3)编译器不知道#的转换作用 用法: #define SIRING(x) #x printf("%s\n",SIRING(Hello World!)); 项目中的用法: #include <stdio.h> #define CALL(f, p) (printf("Call funcyion %s\n",#f, f(p))) int square(int n) { r

weixin_46571142的博客 230

两万字硬核指南!Python爬虫requests库从入门到精通:新手也能搞定所有爬取场景(附实战案例+避坑大全)

请求头是客户端发送给服务器的额外信息,比如User-Agent(浏览器类型)、Referer(来源页面)、Cookie(登录凭证)、(编码方式)等。Cookie是服务器存储在客户端的小型文本文件,包含用户的登录凭证、偏好设置等信息。浏览器会在每次请求时自动携带Cookie,服务器通过Cookie识别用户身份。代理IP是一个中间服务器,你的请求先发送到代理IP,再由代理IP发送到目标网站,目标网站只能看到代理IP的地址,看不到你的真实IP。

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 1496

uniapp开发小程序保存图片权限获取失败一直走fail?本地能保存,线上版就不行! 原来是这个问题!

通过这次经历,我发现线上版小程序和开发版、体验版的权限控制差异较大。如果你也遇到类似的问题,首先要检查是否已勾选“采集用户隐私”,并确保在提交审核时配置了隐私条款。这个设置非常关键,避免像我一样浪费了不少时间和版本。

代码简单说 Vue、JAVA、PHP、Node.js 熟练运用,接口、架构、性能全搞定。 1077

【C/C++】宏定义中的#和##

【C/C++】宏定义中的#和## | 单井号 双井号

Juruo@Security 965

基于STM32LXXX的模数转换芯片ADC(TLA2528IRTER)驱动C程序设计

define TLA2528_ADDR 0x12 << 1 // 用于HAL传输的8位地址(写入为0x24,读取为0x25)// 100kHz (示例值,需根据实际时钟计算)#define TLA2528_REG_PIN_CFG 0x00 // 引脚配置寄存器。#define TLA2528_REG_CHN_SEL 0x01 // 通道选择寄存器。

myron6688的博客 228

【C++】预处理器

预处理器是一些指令,指示编译器在实际编译之前所需完成的预处理。 所有的预处理器指令都是以井号(#)开头,只有空格字符可以出现在预处理指令之前。预处理指令不是 C++ 语句,所以它们不会以分号(;)结尾。 我们已经看到,之前所有的实例中都有 #include 指令。这个宏用于把头文件包含到源文件中。 C++ 还支持很多预处理指令,比如 #include、#define、#if、#else、#line 等,让我们一起看看这些重要指令。 一、#define 预处理 #define 预处理指令用于创建符号常量。该符

qq_36643449的博客 319

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

三十七、C++ 预处理器

C ++提供了下面提到的许多预定义宏 -Sr.No宏观和描述1__LINE__它包含编译时程序的当前行号。2__FILE__它包含编译时程序的当前文件名。3__DATE__它包含一个月/日/年形式的字符串,它是将源文件转换为目标代码的日期。4__TIME__它包含一个形式为hour:minute:second的字符串,它是编译程序的时间。让我们看一下上述所有宏的示例 -return 0;}如果我们编译并运行上面的代码,这将产生以下结果 -

林中静月下仙的博客 533

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

C语言中#和##的使用

# 字符串化 ## 连接符 最后输出结果为 ab,因为#意思是字符串化相当于"ab\n",所以输出结果为ab 最后输出了11、12。因为##是连接符,Day(1)就相当于myday1,myday1的值为11所以输出11。......

qq_41732187的博客 540

第三十四章 C++ 预处理器

第三十四章 C++ 预处理器

2401_89610374的博客 943
上一篇: 编译和运行时的情况,如果在同一个终端或者同一个目录下,如果有两个程序需要连接不同版本的动态库,动态库的问题怎么指定?
下一篇: C++的类型转换之dynamic_cast
吴_知遇
博客等级 码龄7年 100粉丝 26原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值