首页 > 其他分享 >C语言宏的展开规律及其使用

C语言宏的展开规律及其使用

时间:2023-02-24 21:22:21浏览次数:46  
标签:规律 形参 ## C语言 printf 实参 展开 define

https://blog.csdn.net/mary288267/article/details/116499135

1.C语言中嵌套宏的展开规律

一般宏调用的展开规律是,先展开内层宏参数,再展开外层宏函数,所以展开顺序是由内而外。
如果宏定义中某个形参前面有#运算符,则调用此宏定义时,不展开该形参对应的实参,而是直接把这个实参变为字符串。
如果宏定义中某个形参前面有#@运算符,则调用此宏定义时,不展开该形参对应的实参,而是直接把这个实参变为字符。
如果宏定义中某个形参前面或者后面有##运算符,则调用此宏定义时,不展开该形参对应的实参,而是将##运算符前后的实参连接到一起形成一个新的符号,注意不是字符串。
详细实例可见下述代码。
备注:本文参考了 以下链接并作修改。链接:https://blog.csdn.net/aflyeaglenku/article/details/81504256

#include<stdio.h>
#include<iostream>
using namespace std;

#define A(x) T_##x
#define B(x) #@x
#define C(x) #x

#define f(a,b) a##b
#define g(a) #a
#define h(a) g(a)
#define ff(x,y) x+y

#define foo abc
#define foo2(x) x##123
#define foo123 "hehe"

#define Str1 "hello"
#define Cat2Str(x,y) x#y

void main()
{
	printf("%c\n", B(1));       // B(1)------〉'1'
	printf("%s\n", C(1));       // C(1)------〉"1"

	printf("%s\n", h(A(1)));    
	//输出:T_1。
	//宏展开过程为:因h(a)的宏形参前没有#或#@,形参前后没有##,因此先展开宏参数A(1)。
	//h(A(1))→h(T_1)→g(T_1)→"T_1"

	printf("%s\n", h(f(1, 2))); 
	//输出:12.
	//宏展开过程为:因宏h(a)的宏形参前没有#或#@,形参前后没有##,因此先展开宏参数。
	//h(f(1, 2))→h(12)→g(12)→"12"

	printf("%s\n", g(f(1, 2))); 
	//输出:f(1,2)
	//宏展开过程为:因宏g(a)宏定义的形参前有#,则不展开实参f(1,2),而是把实参作为字符串。
	//g(f(1, 2))→#f(1,2)→"f(1,2)"

	printf("%d\n", f(f, f(3, 4)));	
	//输出:7。
	//宏展开顺序为:因宏定义f(a,b)的形参前后有##,因此,不展开实参, f(f, f(3, 4))→ff(3,4)→3+4

	printf("%s\n", g(1)g(2));		//输出:12
	//这个例子很特殊,我原以为编译器不会识别g(1)g(2),事实上,编译后会识别连在一起的宏,然后分别展开。
	
	printf("%s\n", f(g(1), g(2)));	//输出:12	
	//宏展开过程为:因宏定义f(a,b)的形参前后有##,所以不展开实参g(1)和g(2),f(g(1), g(2))展开后变为g(1)g(2),
	//f(g(1), g(2))→g(1)##g(2)→g(1)g(2)→“12”

	printf("%s\n", Cat2Str(Str1, ",nihao"));	//输出:hello",nihao"
	printf("%s\n", Cat2Str(Str1, Str1));		//输出:helloStr1
	//这个例子也比较经典,当宏定义某个形参前有#时,对应宏调用的实参被当作字符串
	//Cat2Str(Str1, Str1)宏展开过程为:
	//因为Cat2Str(x,y)的y参数前有#,直接将后面的参数转为字符串
	//Cat2Str(Str1, Str1)→"hello""Str1"→"helloStr1"

	printf("%s\n", foo2(foo));
	//最后,上个经典例子吧。 foo2(foo)的展开可不是abc123哦。
	//宏展开过程为:因为foo2(x)的宏定义形参前有##,因此,foo2(foo)对应的实参foo不再展开。
	//foo2(foo)→foo##123→foo123→"hehe"
}

宏对应的数值需要使用字符串和数字时

代码1:
void testHong()
{
#define RATE_RAW (15000)	// 需要字符串时使用这个
#define RATE (RATE_RAW)	    // 需要数字时使用这个

#define STR1(R)  #R
#define STR2(R)  STR1(R)

    printf("sample rate is %d\n", RATE);
    printf("sample rate = " STR2(RATE_RAW) "\n");
}

sample rate is 15000
sample rate = (15000)

代码2:
void testHong()
{
#define RATE_RAW 15000	// 需要字符串时使用这个
#define RATE (RATE_RAW)	    // 需要数字时使用这个

#define STR1(R)  #R
#define STR2(R)  STR1(R)

    printf("sample rate is %d\n", RATE);
    printf("sample rate = " STR2(RATE_RAW) "\n");
}

sample rate is 15000
sample rate = 15000

标签:规律,形参,##,C语言,printf,实参,展开,define
From: https://www.cnblogs.com/sggggr/p/17153190.html

相关文章

  • C语言运算符优先级(转载)
    https://www.cnblogs.com/blogernice/articles/13156017.html初级运算符()、[]、->、. 高于 单目运算符  高于 算数运算符(先乘除后加减) 高于 关系运算符......
  • C语言数据结构串的表示与操作的实现
    串的堆分配储存表示typedefstruct{ char*ch;//若是非空字符串,则按串长分配存储区,否则ch为NULL intlength;//串长度}HString;生成一个其值等于串常量的串HStr......
  • C语言中return、break、continue的用法和区别
    C语言中return、break、continue是我们常用的三个“流程控制”关键字。你能熟练使用这三个关键字吗?下面来讲讲这三个关键字,以及相关的内容。 0概述大部分编程语言......
  • C语言运算符优先级
    优先级运算符运算结合关系举例1+单目不变自右向左a*+b1-单目取负自右向左a*-b2*乘自左向右a*b2/除自左向右a/b2%取余自左向右a......
  • C语言可变参数的使用详解
    一、可变参数表介绍c/c++语言具备一个不同于其他编程语言的的特性,即支持可变参数。例如C库中的printf,scanf等函数,都支持输入数量不定的参数。例如:printf("hello world......
  • C语言经典习题(六)
    1.计算偶数的所有质因子输入一个正整数,按照从小到大的顺序输出它的所有质因子(重复的也要列举)输入一个整数输出描述:按照从小到大的顺序输出它的所有质数的因子,以空格隔开。......
  • c语言之各种printf(printf, sprintf, snprintf, swprintf, fprintf, fwprintf, vsprin
    一、v|s|f|n|w的含义v:参数作为va_list一个整体传入s:输出对象为内存缓冲区(char*,wchar_t*)f:输出对象为文件流(char*,wchar_t*)w:宽字符串版本n......
  • c语言单词个数:输入一行英文,输出单词个数 (最开始 中间 最后可能有多个空格)
    #include<stdio.h>//输入一行英文,输出单词个数(最开始中间最后可能有多个空格)#include<string.h>main(){charzf[101];inta,b,c=0,d=0;gets(z......
  • C语言:几位数 乘积
    /*输入一个不大于4位正整数,判断它是几位数,然后输出各位之积。*/#include<stdio.h>main(){inta,cj=1,wei=0,b;scanf("%d",&a);b=a;if(a<=9999......
  • C语言填空:周岁
    /*编写程序,输入一个学生的生日(年:y0、月:m0、日:d0);并输入当前的日期(年:y1、月:m1、日:d1);输出学生的实际年龄周岁*/#include<stdio.h>main(){inty0,m0,d0,y1,m1,d1......