可能重复:
什么是C宏有用?
每隔几个月我就会学到一些C,这是我的废话大学编程教育从未涉及过的.今天它是宏.我对宏的基本理解是它们是一个简单的搜索和替换,它会在编译之前发生在代码上.我无法理解你为什么要使用宏.我正在看的大多数基本例子都是这样的
TEST(a,%d);
#define TEST(a,b) printf(" The value of " #a " = " #b " \n", a)
//which expands to
printf(" The value of a = %d \n",a);
Run Code Online (Sandbox Code Playgroud)
(例子来自这里)
从我的新手角度来看,似乎定义一个新函数会给你相同的结果.我可以看到历史上宏如何在易于搜索和替换之前的几天内快速修改大量源代码,但有些东西告诉我,我错过了一些更重要的观点.
那么宏可以为你做什么样的有用的事情呢?
Tyl*_*nry 65
这不是搜索和替换,它是令牌扩展.C宏是计算世界中每一种其他类型的宏:一种简短而简单的方法,可以让它自动变成更长,更复杂的东西.
使用宏的一个原因是性能.它们是一种消除函数调用开销的方法,因为它们总是在线扩展,不像"内联"关键字,这是编译器经常被忽略的提示,并且在C99之前甚至不存在(在标准中).例如,请参阅与select和pselect使用的fd_sets一起使用的FD_系列宏.这些fd_sets实际上只是位集,FD_宏隐藏了位操作.每次写出自己的比特都会很烦人,如果没有内联,那么函数调用对于如此快速的操作来说将是很多开销.
此外,宏可以做一些功能不能做的事情.考虑令牌粘贴.由于预处理器在编译器之前运行,因此它可以为编译器创建新的标识符.这可以为您提供创建大量类似定义的简便方法,例如
#define DEF_PAIR_OF(dtype) \
typedef struct pair_of_##dtype { \
dtype first; \
dtype second; \
} pair_of_##dtype##_t
DEF_PAIR_OF(int);
DEF_PAIR_OF(double);
DEF_PAIR_OF(MyStruct);
/* etc */
Run Code Online (Sandbox Code Playgroud)
它可以做的另一件事是函数无法将编译时信息转换为运行时信息:
#ifdef DEBUG
#define REPORT_PTR_VALUE(v) printf("Pointer %s points to %p\n", #v, v)
#else
#define REPORT_PTR_VALUE(v)
#endif
void someFunction(const int* reallyCoolPointer) {
REPORT_PTR_VALUE(reallyCoolPointer);
/* Other code */
}
Run Code Online (Sandbox Code Playgroud)
函数无法像输出宏一样在其输出中使用其参数的名称.这也证明了为发布版本编译调试代码.
Deu*_*uro 45
一个原因是直到C99,内联关键字在C语言中不是标准的.因此,宏允许您内联小函数.它们在某些方面也像模板一样工作,即.您不必在宏定义中指定类型,例如:
#define MAX(x,y) ((x) > (y) ? (x) : (y))
Run Code Online (Sandbox Code Playgroud)
这个宏适用于整数,双精度,浮点数等.
Mik*_*aid 16
宏在编译时扩展.你是正确的,他们经常被滥用,但C中的一个经典例子是有一个用于编写调试消息的宏(当编译时关闭调试模式时)不生成任何代码,因此不会导致减速.
i_a*_*orf 12
有时您想要记录,但仅在调试模式下.所以你写了类似的东西:
#ifdef DEBUG
#define LOG_MSG(x) printf(x);
#else
#define LOG_MSG(X)
#endif
Run Code Online (Sandbox Code Playgroud)
有时你只想根据编译时开关关闭或打开一些东西.例如,我的公司对我们的产品做了一些联合品牌,合作伙伴要求解决问题.所以我们会做类似的事情:
#ifndef SPECIAL_PARTNER_BUILD
DoSomethingReallyAwesome();
#endif
Run Code Online (Sandbox Code Playgroud)
然后在给伙伴丢弃时使用-DSPECIAL_PARTNER_BUILD构建.
还有许多其他可能的原因.
有时你只想为你一遍又一遍的事情保存打字.有些人认为这很远(咳嗽 MFC 咳嗽)并在Macros中写出相当于他们自己语言的内容来抽象出一个困难的API.这使得调试成为一个frikkin'的噩梦.
除了功能之外,宏可以有许多不同的用途.
将宏用于任何幻数或字符串相关非常有用.
#define MY_MAGIC_NUM 57
/*MY_MAGIC_NUM used all through out the code*/
Run Code Online (Sandbox Code Playgroud)
C 宏可以在编译时生成代码。这可以(ab)用于有效地创建具有新关键字和行为的特定领域语言。
我最喜欢的例子之一是 Simon Tatham通过宏在 C中实现协程的方法。最简单的宏实现是:
#define crBegin static int state=0; switch(state) { case 0:
Run Code Online (Sandbox Code Playgroud)
是的,有一个无与伦比的支架。其他宏会解决这个问题。