`
Arath
  • 浏览: 47342 次
  • 性别: Icon_minigender_1
  • 来自: 上海
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论
  • LucasLee: 路过。C语言用的很少,看了各位的讨论,长了点见识。感觉C语言的 ...
    双刃剑 - 宏
  • Arath: 模板个人认为是个非常不好的东西,性价比非常不好,只是让程序员多 ...
    双刃剑 - 宏
  • jack: 尝试过近似纯模板的代码,写的很爽,编译时等死...
    双刃剑 - 宏
  • Arath: 在编译器中宏和模板处理的位置不同,其实完全在于C++对于模板的 ...
    双刃剑 - 宏
  • whisper: 所以纯一些的说编译器并不知道宏的存在预处理器都把活干完了模板才 ...
    双刃剑 - 宏

双刃剑 - 宏

阅读更多
在C中使用宏的确是一个非常好的代码手段,可以大量的减少代码量,提高阅读性,通过对一些常用代码的归类写成宏,作用巨大.
例如如下代码:
if(((t->flag & S_FLAG1) || (t->flay & S_FLAG2)) && t->type == T_TYPE1)
...
条件部分如果多次使用到,那么我们完全可以写如下的宏
#define IsXXXX(t) (((t->flag & S_FLAG1) || (t->flay & S_FLAG2)) && t->type == T_TYPE1)
这样上面的代码就成了
if(IsXXXX(t))
...
代码少了很多,而且可读性也增加了很多.
还有一个代码,C中分配一个结构,一般如下代码:
p=(STRUCT*)malloc(sizeof(STRUCT));
是否可以更加漂亮呢?创建一个宏,如下:
#define new(t) (t*)malloc(t)
这样上面的代码就变成了
p=new(STRUCT);
是否有C++的风格了?

但是有利必有弊,宏一旦使用不当反而会产生严重的后遗症,下面随意说几点.
1.给宏赋予太强大的功能,几乎所有的编译器以及大部分的IDE无法展开和定位宏中的代码,所以一旦产生错误,很难调试, 如果真的需要最好还是用函数来封装.

2.宏名字起的不当,这是很致命的,会导致代码可读性大大降低,例如随意将前面例子中的IsXXXX定义为a,然后后面的代码中全是一堆的
if(a(t))
如果这样,键盘是少打了,但是已经完全没有了可读性,也许今天写的这个宏,明天你就忘记这个宏是做什么了. 同时过于简单的名字也会导致同名但是功能不同的宏大量出现,使得代码更难看懂.

3.宏的随意undef,这个是一个很不好的习惯,代码量一旦达到了一定程度,会导致极度的混乱.
例如在某个.h文件中定义了IsXXXX,然后在某个.c中如下使用
#undef IsXXXX
#define IsXXXX(t) (((t->flag & S_FLAG3) || (t->flay & S_FLAG4)) && t->type == T_TYPE2)
这个对于以后的维护修改埋下了极大的隐患.

4.重名,说起来这个算是很多编译器的问题,如果将一个宏的名字和一个变量的名字重名了,那么很多的C Compiler默认状态下不会报警或报错.
例如:
int a;
...
#define a b
这种错误有时候简直可以让人发疯!!!

5.宏的嵌套使用,不是不能这么用,由于宏屏蔽了实际代码,如果宏->宏,那么即使你的宏写的够漂亮明了,恐怕天长日久也就忘记里面具体的逻辑,一旦想修改就很麻烦,所以要小心使用.

到了C++年代,宏的使用少了很多,不过模板几乎就是宏的升级.
说起来在MFC中消息映射就是一套极具特色的宏,如果不了解它也就算了,但是当你看懂了就会感叹宏的魔力!
分享到:
评论
13 楼 LucasLee 2007-04-04  
路过。
C语言用的很少,看了各位的讨论,长了点见识。
感觉C语言的确功能很多啊。
12 楼 Arath 2007-03-26  
模板个人认为是个非常不好的东西,性价比非常不好,只是让程序员多了玩代码的花样而已.
替代的方法其实有很多的.
11 楼 jack 2007-03-26  
尝试过近似纯模板的代码,写的很爽,编译时等死...
10 楼 Arath 2007-03-26  
在编译器中宏和模板处理的位置不同,其实完全在于C++对于模板的要求太高了,所以才成了编译器的噩梦.
代码的迭代要保证正确也要保证效率,真的不好做.
9 楼 whisper 2007-03-24  
所以纯一些的说
编译器并不知道宏的存在
预处理器都把活干完了
模板才是编译器的噩梦
8 楼 simohayha 2007-03-23  
#define 和#include 一样都是预处理器指令,而预处理器是编译过程中单独执行的第一个步骤.

宏还有几个很有意思的用法:
1 #define print(tmp) printf(#tmp " = %d\n",tmp)
调用这个宏时  这里就相当于 printf("tmp = %d\n",tmp);

2 #define join(a,b) a##b

比如调用printf("%d",join(1,2)); 这时就会打印出12
或者int join(a,1)=1;
printf("%d",join(a,1));  这样就会打印出1;

还有一个就是 我怎么感觉 define 有些地方和FP中的lambda有些相似.
7 楼 qiezi 2007-03-22  
jack 写道
模板其中一个作用就是 编译时生成代码, 宏则是编译是展开代码。

虽然功能类似,不过模板的逻辑性要强些,可以自己去设计按某种特殊条件生成特殊的代码。

两个相同的地方,都是静态处理代码,运行时不起作用。

宏是编译时,应该把这个部分分开来看,它必须单独进行一次。经过预编译以后,只剩下#line宏了。。这才是给编译器看的。
6 楼 jack 2007-03-22  
模板其中一个作用就是 编译时生成代码, 宏则是编译是展开代码。

虽然功能类似,不过模板的逻辑性要强些,可以自己去设计按某种特殊条件生成特殊的代码。

两个相同的地方,都是静态处理代码,运行时不起作用。
5 楼 bigpanda 2007-03-21  
这么好的文章,也发到C++圈子吧。:D
4 楼 Arath 2007-03-21  
这个嘛,当然是语法
但是作用吗可以看作用来产生代码
3 楼 qiezi 2007-03-21  
宏不能算语言的一部分。

宏和模板都是用来产生代码的工具。。。
2 楼 Arath 2007-03-21  
模板使用的方法和宏的原理是类似的,只是编译器对模板作了很多特殊语法实现而已
1 楼 simohayha 2007-03-21  
写得不错,不过 "不过模板几乎就是宏的升级."  这句怎么理解?

相关推荐

    2021年超能陆战队观后感.pdf

    然而,金钱同样是一把双刃剑,它能使人获得力量,也可能使人堕落。金钱的道德属性取决于使用它的人和目的。 力量作为影片的核心概念之一,体现在多个层面。小宏的机器人被赋予了强大的力量,成为他复仇和保护他人的...

    DFMEdit编辑工具。。

    DFMEdit是一款强大的并行工程核心技术编辑工具,它在IT领域中主要用于文件的编辑和处理。这个工具以其高效和多功能性赢得了用户的广泛赞誉...但同时,也应认识到技术的双刃剑性质,确保合法合规地使用,避免误入歧途。

    vip免杀教程详细演说

    学习免杀技术的同时,也要明白这些知识的双刃剑性质。尽管掌握免杀技巧可以帮助网络安全专业人员更好地理解恶意软件的工作方式,提高防御能力,但这些技术也可能被不法分子用于非法活动。因此,学习和使用这些知识时...

    access2003

    在数据库应用系统中,数据冗余是一把双刃剑,适当的冗余能保证数据的完整性和可用性,但过度的冗余可能导致数据不一致。因此,保证数据一致性是数据库管理的关键,即在数据更新时,所有冗余副本都应同步更新。 实施...

    Visual C++高级编程技巧(3)

    在C++中,手动内存管理是一把双刃剑,不当使用可能导致内存泄漏或悬挂指针。了解new、delete操作符,理解内存对齐,以及如何使用智能指针(如std::unique_ptr、std::shared_ptr)来自动管理内存,是防止这些问题的...

    奇迹MUsep物品代码.doc

    在第一部分中,我们可以看到波刃剑、短剑、西洋剑等多种武器的定义。这些定义使用十六进制数字表示,例如0x0000、0x0001、0x0002等。这些数字是unique identifier,每个武器都有其唯一的标识符。 接下来,让我们来...

    C:我对C世界的冒险

    安全性和效率是C语言的双刃剑。由于直接操作内存,C语言可能引入缓冲区溢出、空指针解引用等安全问题,需要开发者具备较高的编程技巧。然而,正是这种低级别的控制,使得C语言在性能敏感的应用中占有一席之地。 总...

    24学时攻克c++_笔记

    指针是C++的一个强大特性,但也是一把双刃剑。正确理解和使用指针可以大大提高程序的效率和灵活性,但不当使用会导致诸如空指针解引用和野指针等严重错误。 ### 10. 高级指针 进一步讨论指针的高级应用,如智能...

Global site tag (gtag.js) - Google Analytics