栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

c/c++宏函数和多参宏函数

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

c/c++宏函数和多参宏函数

记住宏函数并非真函数,就是一个字符串的替代动作,预编译阶段处理成真代码

1:基础宏函数

#include 
#include 
#include 

//宏的定义
// 形式:
// #define  宏名称   替换主体

//宏函数的特点:
// 1: 效率高,非真函数,只是字符串替换, 所以结尾";"可有可无
// 2: 可重复调用。
// 3: 核心是字符串替换操作,只是预编译阶段进行的简单的替换,宏也不是类型定义。
// 4:由于是字符串替换,必须要注意结合顺序,给足括号,防止意外。
// 5: 宏 起到指挥编译具体目标的作用,如#ifdef,可见 宏 的主场是预编译阶段。
// 6:辅助实现了可变数量参数功能

//部分预定义宏,在预编译阶段转为实际的代码
// 本机日期              __DATE__
// 文件名                 __FILE__
// 行号                __LINE__
// 本机时间             __TIME__

#define sqr(x) (x)*(x)   //一定要注意括号给足

#define my_pt(x) printf("%s %srn",x,__DATE__)

int main(int argc,char** argv)
{
    printf("ret = %drn",sqr(5+1)); 

    printf("%srn",__DATE__);
    printf("%srn",__TIME__);
    printf("%srn",__FILE__);
    printf("%drn",__LINE__);
    my_pt("this define means string exchange=> ");
    return 0;
}

2:hentai喜欢写的多参宏函数

#include 
#include 
#include 

//__VA_ARGS__需和define一起使用:将左侧宏名称中的...原样抄到右边的__VA_ARGS__地方
#define PT(...)  printf(__VA_ARGS__)    //原样全抄,其实并没啥意义,只是换了个调用名字,在宏内不能增加操作了,还算啥“宏函数”
#define PT_A(...)  printf(__VA_ARGS__"rn")  //简单追加,记住宏的内核是简单替换
#define PT_B(...)  printf("fun in %s,"__VA_ARGS__"rn",__FILE__)  //将传入的替换,并且再做两侧追加系统预定义宏

#define LT(fm,...) printf(fm,__VA_ARGS__)    
// #define LT(fm , ...) printf(fm,__VA_ARGS__,__FILE__)//无法做追加操作,无法编译,其实是替换后的编码格式不对了
// #define LT(fm , ...) printf(fm,__FILE__,__VA_ARGS__)//无法做追加操作

// #define RT(fm,...) printf(fm,##__VA_ARGS__) //单独的##__VA_ARGS__没啥意义
//因为是核心是预编译的字符串替换操作,所以“,”会导致决定是否能编译,即决定编码内容格式。
#define RT_A(fm,...) printf(fm"fun in %s,line %d:rn",##__VA_ARGS__,__FILE__,__LINE__)
#define RT_B(fm,...) printf("fun in %s,line %d:rn"fm,__FILE__,__LINE__,##__VA_ARGS__)  //调整替换追加顺序也可以
//关键处:fm"fun in %s,line %d:rn",##__VA_ARGS__ 
//关键处的关键##__VA_ARGS__
//1:如果可变参数被忽略或为空,## 操作将使预处理器(preprocessor)去除掉它前面的那个逗号
//ep: RT_A("this is const"); =>printf("this is const""fun in %s,line %d:rn",__FILE__,__LINE__)
//2:如果你在宏调用时,确实提供了一些可变参数,GNU CPP 也会工作正常,它会把这些可变参数放到逗号的后面,匹配前面的fm规定格式
//ep: RT_A("a=%d,b=%d,sum=%drn",a,b,a+b); => printf("a=%d,b=%d,sum=%drn""fun in %s,line %d:rn",,a,b,a+b,__FILE__,__LINE__)

//ep:前侧可再多定义一个"参数",format位置也可以调换,但都是和" %s-%d:"连体的。
//#define LOG(Priority,format,...) syslog(LOG_DEBUG," %s-%d:" format,__FILE__,__LINE__,##__VA_ARGS__)
//猜测这个顺序也行#define LOG(Priority,format,...) syslog(LOG_DEBUG,format" %s-%d:",##__VA_ARGS__,__FILE__,__LINE__)
int main(int argc, char ** argv){
    int a = 10; int b = 20;

    PT("this is a simple copy from ... to __VA_ARGS__");   //只能直接copy
    PT_A("this is a simple copy from ... to __VA_ARGS__");

    //注意这里存在一个前提,宏函数必定会对传入数据进行操作,不存在直接完全拷贝的情况,这是无意义的
    PT("this is a simple copy from ... to __VA_ARGS__ %d %d",a,b);
    //能过编译,但这种完全直接拷贝做法毫无意义

    // PT_A("this is a simple copy from ... to __VA_ARGS__ %d %d",a,b); 
    //编译不通过,在宏函数中对传入变量进行了操作,就报字符串连接错误了 
    
    // PT_B("this is a simple copy from ... to __VA_ARGS__%d %d",a,b);  
    //编译不通过,在宏函数中需要操作变量时,出现同上问题
    printf("rn");

    LT("a=%d,b=%d,sum=%drn",a,b,a+b);
    //替换了两段东西,前半段fm,后半段...,所以后半段的,分隔是可变的,反正都去替换为__VA_ARGS__了,所以后半段参数量可变。
    //但是不能在宏函数中追加别的动作了
    printf("rn");

    RT_A("this is const");
    RT_A("a=%d,b=%d,sum=%drn",a,b,a+b);
    RT_B("a=%d,b=%d,sum=%drn",a,b,a+b);
}

结合下面两个地址看:

https://www.codersrc.com/archives/9450.html

https://www.codersrc.com/archives/9480.html

常见还有常见宏使用的#,##用法:

#:

把后面的参数换成参数字符串

//和define定义的宏函数一起使用,获得 传入宏函数的参数的变量名。
#define new_print(A) printf(%s  %d rn“,#A,A);
int main(){
	int age = 10;
	new_print(age);
}
=》  age  10

##:(宏函数内的粘接剂)

#define new_fun(parm)  print##parm("this is a printfrn");
int main()
{
//new_fun(oh); //无法编译通过
new_fun(f);
    return 0;
}
=》this is a printf

即等于最终执行了printf("this is a printfrn");

linux内核中的#define有大量出现##这个粘接剂ep:

#define MAX8925_LDO(_id, min, max, step)			
{								                    
	.desc	= {						                 
		.name	= "LDO" #_id,				          
		.ops	= &max8925_regulator_ldo_ops,		
		.type	= REGULATOR_VOLTAGE,			    
		.id	= MAX8925_ID_LDO##_id,			       
		.owner	= THIS_MODULE,				        
	},							                    
	.step_uV	= step * 1000,				           
	.vol_reg	= MAX8925_LDOVOUT##_id,			 
	.vol_shift	= 0,					              
	.vol_nbits	= 6,					            
	.enable_reg	= MAX8925_LDOCTL##_id,			
	.enable_bit	= 0,					        
}

  

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1034168.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号