C/C++ #运算符、##运算符、变参宏 ...和_ _VA_ARGS_ _

文章目录

  • 用宏参数创建字符串:#运算符
    • 函数宏
    • #号作为一个预处理运算符,可以把记号转换成字符串
  • 预处理器粘合剂:##运算符
  • 变参宏:...和_ _VA_ARGS_ _
  • 参考

用宏参数创建字符串:#运算符

函数宏

下面是一个类函数宏:

#define PSQR(X) printf("The square of X is %d.\n", ((X)*(X)));

假设这样使用宏:

PSQR(8);

输出为:

The square of X is 64.

注意双引号字符串中的X被视为普通文本,而不是一个可被替换的记号。

#号作为一个预处理运算符,可以把记号转换成字符串

C允许在字符串中包含宏参数。
在类函数宏的替换体中,#号作为一个预处理运算符,可以把记号转换成字符串
例如,如果x是一个宏形参,那么#x就是转换为字符串"x"的形参名。这个过程称为字符串化(stringizing)。

/* subst.c -- 在字符串中替换 */
#include <stdio.h>
#define PSQR(x) printf("The square of " #x " is %d.\n",((x)*(x)))
int main(void)
{int y = 5;PSQR(y);PSQR(2 + 4);return 0;
}

该程序的输出如下:

The square of y is 25.
The square of 2 + 4 is 36.

调用第1个宏时,用"y"替换#x。
调用第2个宏时,用"2 + 4"替换#x。

预处理器粘合剂:##运算符

与#运算符类似,##运算符可用于类函数宏的替换部分。
而且,##还可用于对象宏的替换部分。
##运算符把两个记号组合成一个记号。
例如,可以这样做:

#define XNAME(n) x ## n

然后,宏

XNAME(4)

将展开为
x4
程序演示了##作为记号粘合剂的用法。

// glue.c -- 使用##运算符
#include <stdio.h>
#define XNAME(n) x ## n
#define PRINT_XN(n) printf("x" #n " = %d\n", x ## n);
int main(void)
{int XNAME(1) = 14; // 变成 int x1 = 14;int XNAME(2) = 20; // 变成 int x2 = 20;int x3 = 30;PRINT_XN(1); // 变成 printf("x1 = %d\n", x1);PRINT_XN(2); // 变成 printf("x2 = %d\n", x2);PRINT_XN(3); // 变成 printf("x3 = %d\n", x3);return 0;
}

该程序的输出如下:

x1 = 14
x2 = 20
x3 = 30

注意,PRINT_XN()宏用#运算符组合字符串,##运算符把记号组合为一
个新的标识符。

变参宏:…和_ VA_ARGS _

一些函数(如 printf())接受数量可变的参数。
C99/C11也对宏提供了这样的工具。虽然标准中未使用“可变”(variadic)这个词,但是它已
成为描述这种工具的通用词(虽然,C标准的索引添加了字符串化(stringizing)词条,但是,标准并未把固定参数的函数或宏称为固定函数和不变宏)。

通过把宏参数列表中最后的参数写成省略号(即,3个点…)来实现这一功能。这样,预定义宏_ VA_ARGS _可用在替换部分中,表明省略号代表什么。例如,下面的定义:

#define PR(...) printf(_ _VA_ARGS_ _)

假设稍后调用该宏:

PR("Howdy");
PR("weight = %d, shipping = $%.2f\n", wt, sp);

对于第1次调用,_ _VA_ARGS_ _展开为1个参数:"Howdy"
对于第2次调用,_ _VA_ARGS_ _展开为3个参数:"weight = %d,shipping = $%.2f\n"、wt、sp
因此,展开后的代码是:

printf("Howdy");
printf("weight = %d, shipping = $%.2f\n", wt, sp);

程序演示了一个示例,该程序使用了字符串的串联功能和#运算符。

// variadic.c -- 变参宏
#include <stdio.h>
#include <math.h>
#define PR(X, ...) printf("Message " #X ": " __VA_ARGS__)
int main(void)
{double x = 48;double y;y = sqrt(x);PR(1, "x = %g\n", x);PR(2, "x = %.2f, y = %.4f\n", x, y);return 0;
}

第1个宏调用,X的值是1,所以#X变成"1"。
展开后成为:

print("Message " "1" ": " "x = %g\n", x);

然后,串联4个字符,把调用简化为:

print("Message 1: x = %g\n", x);

下面是该程序的输出:

Message 1: x = 48
Message 2: x = 48.00, y = 6.9282

记住,省略号只能代替最后的宏参数:

#define WRONG(X, ..., Y) #X #_ _VA_ARGS_ _ #y //不能这样做

参考

《C Primer Plus》

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

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

相关文章

MongoDB入门级别教程全(Windows版,保姆级教程)

下载mongodb 进入官网&#xff1a; Download MongoDB Community Server | MongoDB 选择msi&#xff0c;Windows版本 下载完后直接双击&#xff1a; 选择complete 这里建议改地方&#xff1a; 我这里直接改成d盘&#xff1a;work目录下面&#xff1a; 点击next&#xff1a; 因…

spring cloud-注册中心(Eureka)

一、服务注册中心组件(*) 定义&#xff1a;服务注册中心就是在整个微服务架构单独抽取一个服务&#xff0c;该服务不做项目中任何业务功能&#xff0c;仅用来在微服务中记录微服务、对微服务进行健康状态检查&#xff0c;及服务元数据信息存储常用的注册中心&#xff1a;eurek…

[蓝桥杯复盘] 第 3 场双周赛20231111

[蓝桥杯复盘] 第 3 场双周赛20231111 总结深秋的苹果1. 题目描述2. 思路分析3. 代码实现 鲜花之海1. 题目描述2. 思路分析3. 代码实现 斐波拉契跳跃2. 思路分析3. 代码实现 星石传送阵2. 思路分析3. 代码实现 六、参考链接 总结 做了后4题。https://www.lanqiao.cn/oj-contes…

『亚马逊云科技产品测评』活动征文|阿里云服务器亚马逊服务器综合评测

授权声明&#xff1a;本篇文章授权活动官方亚马逊云科技文章转发、改写权&#xff0c;包括不限于在 Developer Centre, 知乎&#xff0c;自媒体平台&#xff0c;第三方开发者媒体等亚马逊云科技官方渠道 文章目录 引言一、亚马逊&阿里云发展历史介绍1.1 亚马逊发展历史1.2…

【开题报告】基于JavaWeb的奢侈品选购平台的设计与实现

1.研究背景 基于JavaWeb的奢侈品选购平台的设计与实现项目背景可以从奢侈品行业的发展趋势、消费者需求和电子商务的发展等方面展开阐述。 &#xff08;1&#xff09;奢侈品行业的发展趋势 随着中国经济的不断增长和居民收入水平的提高&#xff0c;奢侈品市场呈现出持续增长的…

【 OpenGauss源码学习 —— 列存储(CStore)(六)】

列存储&#xff08;CStore&#xff09;&#xff08;六&#xff09; 概述CStore::GetCUDataFromRemote 函数CStore::CheckConsistenceOfCUDescCtl 函数CStore::CheckConsistenceOfCUDesc 函数CStore::CheckConsistenceOfCUData 函数额外补充 声明&#xff1a;本文的部分内容参考…

使用记录-MongoDB

find常用方法 在 MongoDB 的 find 方法中&#xff0c;可以使用各种查询操作符来执行不同类型的查询。其中之一是 $in 操作符&#xff0c;它用于在一个字段中匹配多个值。 $eq 操作符&#xff1a; 用于匹配字段值等于指定值的文档。 // 查询 age 字段等于 25 的文档 db.colle…

Centos, RockyLinux 常用软件安装汇总

一、基本指令&#xff1a; 命令作用clear清屏pwd显示当前路径cat / more显示文本文档uname -a查看当前版本hostnamectl查看当前版本cat /etc/redhat-release查看当前版本free查看剩余内存df -h[查看磁盘剩余空间]du -sh 查看文件夹名"dir"占用的空间lsof -i:8080查看…

【chat】 1:Ubuntu 20.04.3 编译安装moduo master分支

muduo 基于reactor反应堆模型的多线程C++网络库大佬的官方仓库有cpp17分支看了下cmakelist文件里面还是要依赖不少库,比如boost protobuf而且cpp17 似乎 是2021年的master 是2022更新的那么还是选择master吧。ubuntu版本 Ubuntu 20.04.3 root@k8s-master-2K4G:~# uname -a Lin…

SQL 撤销索引、表以及数据库||SQL CREATE DATABASE 语句||SQL CREATE TABLE 语句

SQL 撤销索引、表以及数据库 通过使用 DROP 语句&#xff0c;可以轻松地删除索引、表和数据库。 DROP INDEX 语句 DROP INDEX 语句用于删除表中的索引。 用于 MS Access 的 DROP INDEX 语法&#xff1a; DROP INDEX index_name ON table_name 用于 MS SQL Server 的 D…

MySQL 报错 incorrect datetime value ‘0000-00-00 00:00:00‘ for column

使用navicat导入数据时报错&#xff1a; MySQL 报错 incorrect datetime value ‘0000-00-00 00:00:00’ for column 这是因为当前的MySQL不支持datetime为0的情况。 MySQL报incorrect datetime value ‘0000-00-00 00:00:00’ for column错误原因&#xff0c;是由于在MySQL5.7…

【原创】java+swing+mysql车辆维修管理系统设计与实现

摘要&#xff1a; 车辆维修管理系统是一个用于管理和追踪车辆维修过程的系统&#xff0c;它能够提高效率&#xff0c;减少错误&#xff0c;并提供详细的车辆历史记录&#xff0c;可以帮助车辆维修企业实现信息化管理&#xff0c;提高工作效率和客户满意度&#xff0c;降低运营…

Go 语言

1. 请简要介绍一下 Go 语言的特点。 Go 语言是一种高性能、并发支持强大且易于学习的编程语言。以下是 Go 语言的一些主要特点&#xff1a; 高性能&#xff1a;Go 语言的运行速度接近 C 和 Java&#xff0c;某些场景下甚至更快&#xff0c;这使得它非常适合用于高性能计算和网…

DevEco studio配置自己的虚拟环境

开始使用DevEco studio时使用的时华为预置的手机&#xff0c;通过网络访问&#xff0c;但是近期发现有两点问题 网络不稳定的时候机器很卡现在资源很难使用 DevEco提供了自定义环境的搭建&#xff0c;从而解决上面的问题 这里有几点问题需要硬盘至少10G空闲&#xff08;应该问题…

【考研数据结构代码题6】构建二叉树及四大遍历(先中后层)

题目&#xff1a;请你编写完整的程序构建一棵二叉树并对其进行先序遍历、中序遍历、后序遍历与层次遍历&#xff0c;分别打印并输出遍历结果 难度&#xff1a;★★★ 二叉树的存储结构 typedef struct Node{char data;//数据域struct Node* left;//左子树struct Node* right;//…

【评论送书】十本架构师成长和软件架构技术相关的好书(可以任选)

正文开始前给大家推荐个网站&#xff0c;前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。 参与规则 本次送书1~5本参与方式&#xff1a;关注博主、点赞、收藏、评论&#xff08;从评论区…

[工业自动化-18]:西门子S7-15xxx编程 - 软件编程 - PLC用于工业领域的嵌入式系统:硬件原理图、指令系统、系统软件架构、开发架构等

目录 前言&#xff1a; 一、PLC的硬件电路原理 1.1 硬件框图 1.2 硬件模块详解 &#xff08;1&#xff09;CPU &#xff08;2&#xff09;存储器 &#xff08;3&#xff09;输入/输出&#xff08;I/O&#xff09;模块 &#xff08;4&#xff09;编程器 &#xff08;5&a…

Flume(一)【Flume 概述】

前言 今天实在不知道学点什么好了&#xff0c;早上学了3个多小时的 Flink &#xff0c;整天只学一门技术是很容易丧失兴趣的。那就学点新的东西 Flume&#xff0c;虽然 Kafka 还没学完&#xff0c;但是大数据生态圈的基础组件也基本就剩这倆了。 Flume 概述 生产环境中的数据一…

一道 python 数据分析的题目

python 数据分析的题目。 做题方法&#xff1a;使用 pandas 读取数据&#xff0c;然后分析。 知识点&#xff1a;pandas&#xff0c;正则表达式&#xff0c;py知识。 过程&#xff1a;不断使用 GPT&#xff0c;遇到有问题的地方自己分析&#xff0c;把分析的结果告诉 GPT&am…

深入了解HTTP与HTTPS关键差异与底层原理

文章目录 历史发展HTTP的历史发展&#xff1a;HTTPS的历史发展&#xff1a; HTTP与HTTPS的区别和联系HTTP与HTTPS的底层原理HTTP的底层原理&#xff1a;HTTPS的底层原理&#xff1a; HTTP与HTTPS的协议组成HTTP协议的组成部分&#xff1a;HTTPS协议的组成部分&#xff1a;TLS&a…