当前位置:   article > 正文

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

c语言宏对字符串的使用

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

  1. int Flower = 1;
  2. int Fruit = 2;
  3. int Vegetables = 3;
  4. int GetFlowerId()
  5. {
  6. return Flower;
  7. }
  8. int GetFruitId()
  9. {
  10. return Fruit;
  11. }
  12. int GetVegetablesId()
  13. {
  14. return Vegetables;
  15. }

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

  1. DeclareGetNameId(Flower);
  2. DeclareGetNameId(Fruit);
  3. DeclareGetNameId(Vegetables);

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

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

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

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

  1. #define DefineGetNameId(name)
  2. int Get##name##id()
  3. {
  4. return name;
  5. }
  6. DefineGetNameId(Flower)
  7. DefineGetNameId(Fruit)
  8. DefineGetNameId(Vegetables)

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

  1. #define DefineGetNameId(name)
  2. DeclareGetNameId(name)
  3. {
  4. return name;
  5. }

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

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

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

  1. #define NameFactory(name) Get##name##Id
  2. #define GetNameId(name) NameFactory(name)()
  3. #define DeclareGetNameId(name) int GetNameId(name)
  4. #define DefineGetNameId(name)
  5. DeclareGetNameId(name)
  6. {
  7. return name;
  8. }

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

  1. #define NameFactory(name) Get##name
  2. #define GetNameInst(name) NameFactory(name)()
  3. #define DeclareGetNameInst(type, name) type GetNameInst(name)
  4. #define DefineGetNameInst(type, name)
  5. DeclareGetNameInst(type, name)
  6. {
  7. return name;
  8. }

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

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

  1. DeclareGetNameInst(int, Flower);
  2. DefineGetNameInst(int, Flower)

展开如下:

  1. int GetFlower();
  2. 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、#@表示字符替换。看两个小例子:

  1. #define ToChar(x) #@x
  2. #define ToString(x) #x

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

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/600730
推荐阅读
相关标签
  

闽ICP备14008679号