宏能否定义字符串_C语言花里胡哨的宏的用法

我们偶尔会在代码里看到这样的用法:

int Flower = 1;
int Fruit = 2;
int Vegetables = 3;
int GetFlowerId()
{
	return Flower;
}
int GetFruitId()
{
	return Fruit;
}
int GetVegetablesId()
{
	return Vegetables;
}

三个函数在其他地方有调用,find一下声明又find不到。找来找去找到个类似声明的写法:

DeclareGetNameId(Flower);
DeclareGetNameId(Fruit);
DeclareGetNameId(Vegetables);

其宏函数的定义有可能是长这样的:

#define DeclareGetNameId(name) int Get##name##Id()

宏定义中,##表示字符串拼接,一般用于消除大面积的结构性重复比如上面的例子。

什么?你想把函数定义里的重复也消掉?也可以:

#define DefineGetNameId(name) 
int Get##name##id() 
{ 
	return name; 
}

DefineGetNameId(Flower)
DefineGetNameId(Fruit)
DefineGetNameId(Vegetables)

这段代码还有重复,好吧定义里有一行可以直接用声明替换,再改改:

#define DefineGetNameId(name) 
DeclareGetNameId(name) 
{ 
	return name; 
}

什么?调用点也想用这种花里胡哨的方法?行,给你一个:

#define GetNameId(name) Get##name##Id()

又重复了,好吧调用点用的宏和声明用的宏里面Get##name##Id出现了两次,看来得为这个东西单独写个宏了:

#define NameFactory(name) Get##name##Id
#define GetNameId(name) NameFactory(name)()

#define DeclareGetNameId(name) int GetNameId(name)
#define DefineGetNameId(name) 
DeclareGetNameId(name) 
{ 
	return name; 
}

上面这段代码可以作为你的工具库,走到哪儿带到哪儿。什么?名字不通用?同时你还想返回别的类型?好吧我们改改:

#define NameFactory(name) Get##name
#define GetNameInst(name) NameFactory(name)()

#define DeclareGetNameInst(type, name) type GetNameInst(name)
#define DefineGetNameInst(type, name) 
DeclareGetNameInst(type, name) 
{ 
	return name; 
}

这段代码已经做了非常多的消除重复的动作,终于可以作为程序员必备了吧?

下面我们验证一下。使用gcc -E x.c可以生成预处理文件,也就是把宏展开后生成一个文件,默认打在terminal,通过gcc -E x.c > x.i打印到x.i里,代码如下:

DeclareGetNameInst(int, Flower);
DefineGetNameInst(int, Flower)

展开如下:

int GetFlower();
int GetFlower() { return Flower; }

下面我们总结一下这个写法的优缺点:优点已经体现得比较清楚了,代码整洁,重复度低;缺点在本文开头也说过了,无法通过IDE的find定义、声明、调用功能进行代码阅读,代码阅读是无法流畅的。

下面谈一下具体工作中应该怎么选:宏函数这个东西,能不用则不用,毕竟安全性不太行。但凡事有个例外,假如3个同质函数可以忍,30个300个呢?太多就用吧。

延伸阅读(例子来源于多个帖子):

我们已经知道了##是用来进行拼接的。下面还有几个小知识点:

1、#表示字符串替换。网上常见的例子是这样

#define example(instr) printf("the input string is:t%sn",#instr);

example(abc);展开之后:

printf("the input string is:t%sn","abc");

2、#@表示字符替换。看两个小例子:

#define ToChar(x) #@x
#define ToString(x) #x

char a = ToChar(1);结果就是a='1';

char* str = ToString(123132);就成了str="123132";

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值