首页 > 其他分享 >C语言宏定义中的#和##

C语言宏定义中的#和##

时间:2023-07-16 20:01:15浏览次数:37  
标签:记号 ## C语言 int printf 实参 define 定义

#和##是宏定义中常用的两个预处理运算符

其中#用于记号串化,##用于记号黏结,下面分别介绍它们。

C语言宏定义中的#和##_字符串

1. 记号串化(#)

记号串化可以将函数式宏定义中的实参转换为字符串。在函数式宏定义中,如果替换列表中有“#”,则其后的预处理记号必须是当前宏的形参。在预处理期间,“#”连同它后面的形参一起被实参取代。例如

#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);
    PSQR( 3   *   2  );
    return 0;
}

程序运行结果如下:

C语言宏定义中的#和##_函数式_02

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

C语言宏定义中的#和##_函数式_03

ANSI C字符串的串联特性将这些字符串与printf()语句的其他字符串组合,生成最终的字符串。例如,第1次调用变成:

printf("The square of " "y" " is %d.\n",((y)*(y)));

然后,字符串串联功能将这3个相邻的字符串组合成一个字符串:

"The square of y is %d.\n"

如果传入的实参中间有空白,则不管有多少,都被转换为一个空格,参数开头和末尾的空白都被删除。例如第3次调用宏时,实参“3   *   2  ”转换为“3 * 2”。

2. 记号黏结(##)

与#运算符类似,##运算符可用于函数式宏的替换部分,它把两个记号组合成一个记号。例如,可以这样定义函数式宏:

C语言宏定义中的#和##_函数式_04

#define XNAME(n) x ## n

然后,展开宏XNAME(4)为x4。

记号黏结的作用是将几个预处理记号合并为一个。在一个函数式宏定义中,如果一个预处理记号的前面或者后面有"##",则该记号将与它前面或者后面的记号合并,如果该预处理记号是宏的形参,则用实参执行合并。例如:

#define F(x, y, z)   x##y##r
char F(a, b, c);

第2行的宏调用,其扩展之后如下:

char abr;

需要注意的是,在函数式宏定义中,“##”不能位于替换列表的开头和结尾。

#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; // 转换为 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;
}

程序运行结果如下。

C语言宏定义中的#和##_字符串_05

3. 分析程序运行结果

C语言宏定义中的#和##_#define_06

#include <stdio.h>
#define f(a,b) a##b
#define g(a)   #a
#define h(a) g(a)
int main()
{
    printf("h(f(1,2))展开为:%s\n",h(f(1,2)));
    printf("g(f(1,2))展开为:%s\n",g(f(1,2)));
    return 0;
}

宏展开顺序大致可以归结为:

第一步:首先用实参代替形参,将实参代入宏文本中

第二步:如果实参也是宏,则展开实参

第三步:最后继续处理宏替换后的宏文本,如果仍包含宏,则继续展开

注意:如果在第二步,实参代入宏文本后,实参之前或之后遇到#或##,实参不再展开

根据以上宏展开步骤分析第8行的宏调用h(f(1,2)),其展开步骤为:

h(f(1,2))-->g(f(1,2))-->g(1##2)-->g(12)-->"12"

第9行的宏调用g(f(1,2)),其展开步骤为:

g(f(1,2))-->#f(1,2)-->"f(1,2)"

上面程序运行结果如下。

C语言宏定义中的#和##_字符串_07

标签:记号,##,C语言,int,printf,实参,define,定义
From: https://blog.51cto.com/u_15641375/6739774

相关文章

  • window版redis设置密码后不生效
    背景环境winserver2012,redis-x64-3.0.504,java1.8由于历史遗留原因,部分老软件是部署在winserver上,尽着能不动就不动的原则,一直保留至今,软件也一直正常运行,但是最近机器扛不住了,只好迁移问题reids虽然在配置文件中配置了requirepass密码,但是一直不生效,即使redis.windows.conf......
  • #yyds干货盘点# LeetCode程序员面试金典:分数到小数
    题目:给定两个整数,分别表示分数的分子 numerator和分母denominator,以字符串形式返回小数。如果小数部分为循环小数,则将循环的部分括在括号内。如果存在多个答案,只需返回任意一个。对于所有给定的输入,保证答案字符串的长度小于104。 示例1:输入:numerator=1,denominator......
  • python中tk无线按钮使用方法
    先上代码:fromtkinterimport*root=Tk()selected_var=IntVar()radiobutton=Radiobutton(root,text='hzq1',variable=selected_var,value=88)radiobutton.pack()radiobutton2=Radiobutton(root,text='hzq2',variable=selected_var,value......
  • 可维护性测试指南
    可维护性测试什么是可维护性测试?维护的主要定义是保持或维持特定状态的过程。软件的可维护性由开发人员负责,他们定期修改软件以满足不断变化的客户需求并解决客户提出的问题。软件维护需要增强软件的功能,以包含客户需要的新功能,修改代码以避免将来出现问题,修复代码中的缺陷或错......
  • 三通道激光恒流源 数据测试
    前端整流部分空载不带电容输出:都使用耐压35v电容测试,10000uf为绿色高频电容类型(优信):不带负载:10000uf电容滤波效果47000uf电容滤波:(和没上220v供电一致,,)带1r电阻负载:47000uf&10000uf电容对比 ......
  • Educational Codeforces Round 33 (Rated for Div. 2)
    EducationalCodeforcesRound33(RatedforDiv.2)https://codeforces.com/contest/893昨日vp,今日补完FD贪心,思路值得学习;E组合数学推式子,式子不难,关键在于模型抽象F主席树,调了老半天,关键在于要理解查询函数的含义,确定什么时候能返回。A.ChessForThree居然卡了快十分......
  • 提交错了 git 标签
    因为需要将FastAdmin适配php8,对FastAdmin使用到的think-captcha做了一下更新。不过在打了标签后发现吧没有用到的tag(v2v3)也给提交到了仓库中。如果一个一个手工在网页端删除太慢了,所以就找到了一下相关的命令,这里记录一下。gitshow-ref--tag|awk'/v2\.[0-9]{1}[......
  • 生物信息常见聚类算法
    UPGMA(UnweightedPairGroupMethodwithArithmeticMean)是一种常用的聚类分析方法,用于构建进化树或聚类树。它基于样本之间的相似性或距离矩阵,将样本逐步合并成群集,并计算新群集的平均距离。UPGMA的基本原理是按照距离最小的原则,通过计算两个最相似样本之间的平均距离来合并它......
  • 3D渲染速度慢,花重金买显卡还是用云渲染更划算
    3D渲染对建筑师和设计师来说并不陌生,3D渲染的过程中出现渲染卡顿、特殊材质难以渲染,或者本地配置不足、本地渲染资源不够时,常常会影响工作效率。本文比较了3D渲染时,为提高工作效率,买显卡还是用云渲染更划算,希望对大家有帮助。3D渲染速度慢通常带来以下痛点:工作效率低下:慢的渲染......
  • octave的ztrans/iztrans ,z变换与z反变换无法使用的问题
    octave不是matlab,截止2023-07-16,octave还没有实现……,开源社区嘛,好多都是爱好者,多包容。通过这个链接可以追踪进度https://github.com/cbm755/octsympy/issues?q=iztrans+......