user-0 提问: 谁能形象的讲解一下宏定义的作用？

回复:
user: user-1
content: 你和小伙伴约定，我喊 1，你就读：一行白鹭上青天 #define a abcdefg（也可以是很长一段代码一个函数） 同理宏就相当于你和编译器之间的约定，你告诉它 我写 a 就是后面那段内容。 okay，预编译的时候 它一看噢 a是这个 它就在这时候把所有的a都替换成了后面那个。

user: user-2
content: 宏有两种 1）不带参数的宏       宏常量，以及其他各种宏表达式      这种宏 通常会直接替换掉      2）带参宏，可以当作函数用 这种宏，替换的时候，参数也相应的替换掉

user: user-3
content: #与##在宏定义中的--宏展开 #include <stdio.h> #define f(a,b) a##b #define g(a)   #a #define h(a) g(a) int main() {         printf("%s\n", h(f(1,2)));   // 12         printf("%s\n", g(f(1,2))); // f(1,2)         return 0; } 宏展开时： 如果宏定义以#开头，不展开参数，直接替换。 故g(f(1,2))--->#f(1,2)--->"f(1,2)"； 如果宏定义不以#开头，展开参数，直接替换，由外层向里层，如果碰到的是#开头的宏，不继续往里层展开，往外层展开。 由外层向里层，如果碰到的是以非#开头的宏，继续往里层走，直至最里层，开始一层层往外层展开。 故h(f(1,2))--->h(12)--->g(12)---->#12----->"12"。 PS： ##在宏中定义，是字符连接符 如a##b##c 等同于 "abc" #在宏开头出现，是表示宏展开的方式不同 #a 等同于"a" #abc 等同于 "abc" 复杂的: #include <stdio.h> #define f(a,b) a##b #define g(a)   #a #define h(a) g(a) int main() {         char a = 'a';         cout<<g(a)<<endl; // a         cout<<g(g(a))<<endl; // a         printf("%s\n", h(f(1,2)));   // 12         printf("%s\n", g(f(1,2))); // f(1,2)         printf("%s\n", g(h(f(1,2)))); // h(f(1,2))         printf("%s\n", h(g(f(1,2)))); // "f(1,2)"         printf("%s\n", h(h(f(1,2)))); // "12"         system("pause");         return 0; } 预处理后的：（在编译选项中添加/EP /P后编译生成的.i文件。gcc加-E） int main() {         char a = 'a';         cout<<"a"<<endl;         cout<<"g(a)"<<endl;         printf("%s\n", "12");         printf("%s\n", "f(1,2)");         printf("%s\n", "h(f(1,2))");         printf("%s\n", "\"f(1,2)\"");         printf("%s\n", "\"12\"");         system("pause");         return 0; } --------------------------------------------------- 宏解析 1.       ##操作符 ##操作符它的作用是在替代表中将其前后的参数连接成为一个预处理符号，它不能出现于宏替代表的开端和末尾。 例： #define concat(s,t) s##t #define AAA ABC concat(A, AA) 将被替换成 ABC 2.       重新扫描和替换 在替换列表中的所有参数替换过之后，预处理器将对结果token序列重新扫描以便对其中的宏再次替换。 当正在替换的宏在其替换列表中发现自身时，就不再对其进行替换。在任何正在嵌套替换的宏的替换过程中遇到正被替换的宏就对其不再进行替换（防止递归）。 例： #define ROOT AAA CCC #define AAA ROOT ROOT 将被替换成 ROOT CCC

user: user-4
content: http://en.cppreference.com/w/cpp/preprocessor/replace

user: user-5
content: 代码替换，注意是代码级替换，不是变量的赋值。注意！注意！注意！ 通常用法： （1）常量代换，如#define  BTN_FILE  1    #define BTN_EDIT  2 （2）调试使用：#define DEBUG （3）.h文件头防止重复包含 等等

user: user-6
content: 如果能形象地描述出来，那就不是宏定义了

user: user-3
content: VC编译选项加/EP /P（项目、属性、配置属性、C/C++、预处理器、预处理到文件：是，预处理取消显示行号：是），重新编译，查看宏展开后对应的.i文件。gcc加-E http://bbs.csdn.net/topics/391003898

user: user-7
content: 宏定义分类：   （1）不带参数的宏定义   形式： #define 宏名 [宏体] 功能：可以实现用宏体代替宏名 使用实例： #define TRUE 1 作用：程序中多次使用TRUE，如果需要对TRUE的值进行修改，只需改动一处就可以了     （2）带参数的宏： #define 宏名 ( 参数表) [宏体]     宏定义作用：   （1）方便程序的修改   上面的#define TRUE 1就是一个实例   （2）提高程序的运行效率   宏定义的展开是在程序的预处理阶段完成的，无需运行时分配内存，能够部分实现函数的功能，却没有函数调用的压栈、弹栈开销，效率较高  （3）增强可读性   这点不言而喻，当我们看到类似PI这样的宏定义时，自然可以想到它对应的是圆周率常量   （4）字符串拼接    例如： #define CAT(a,b,c) a##b##c   main() {     printf("%d\n" CAT(1,2,3));     printf("%s\n", CAT('a', 'b', 'c'); }   程序的输出会是：   123 abc     （5）参数转化成字符串   示例：   #defind CAT(n) "abc"#n   main() {     printf("%s\n", CAT(15)); }   输出的结果会是 abc15   （6）用于程序调试跟踪 常见的用于调试的宏有，_ L I N E _，_ F I L E _，_ D A T E _，_ T I M E _，_ S T D C _ （7）实现可变宏 举例来说： #define PR(...) printf(_ _VA_ARGS_ _)

user: user-8
content: 代码级别文本展开，改的是代码本身，很强大，所以不要乱用