#与##在宏定义中的--宏展开
#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文件)
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
- 浏览: 155493 次
- 性别:
- 来自: 上海
最新评论
-
oyhuang:
看不懂啊,这么多行
麻将胡牌逻辑 java -
墙头上一根草:
最近项目在上线 所以好久没上来了 这个确实是我研究不够透彻 ...
mybatis中不能出现小于号 -
Tyrion:
...不是说不支持“<”而是因为你用的是xml文件配置, ...
mybatis中不能出现小于号 -
add2ws:
小于和大于号和xml里的尖括号冲突,应该用<和& ...
mybatis中不能出现小于号 -
hellotieye:
楼主 mybatis 是可以使用小于号的 再好好学一下 没关系 ...
mybatis中不能出现小于号
相关推荐
### C++/C宏定义(define)中#与##的含义及应用 #### 一、引言 在C++和C语言中,预处理器指令`#define`被广泛用于定义宏,这些宏可以包含简单的替换文本,也可以进行复杂的条件判断和参数处理。本文将详细介绍宏...
根据提供的文档标题、描述以及部分代码内容,我们可以总结出关于C++宏定义的一些实用技巧,特别是涉及到了“#”和“##”的操作符在宏定义中的应用。下面将详细解析这些知识点。 ### C++宏定义基础 在C++中,宏是一...
### C++宏的使用总结 #### 一、概述 本文档详细介绍了C++中的宏使用技巧,涵盖了条件包含、条件编译、定义常量、可变参数宏以及宏的组合等多个方面。通过这些实例,可以帮助读者更好地理解和运用宏,从而提高编程...
6. **参数预扫描**:宏参数在宏体中使用前会先展开,除非在`#`或`##`操作符之后,这种情况下参数不会被展开。例如`PARAM(ADDPARAM(1))`会先展开`ADDPARAM(1)`为`INT_1`,然后`PARAM(INT_1)`得到`INT_1`。 7. **宏...
在C/C++编程中,宏定义(#define)是一种预处理器指令,用于创建符号常量或简单的文本替换。宏在程序编译时起作用,它不是真正的函数,但可以通过模拟函数调用来实现类似的功能,从而提高代码的可读性和可维护性。在...
根据给定文件的信息,我们可以总结出以下关于C++宏的相关知识点: ### 宏的基本概念 在C++中,宏是一种预处理指令,主要用于文本替换。它由预处理器处理,并在编译之前完成替换操作。宏可以用于定义常量、创建简短...
在编程领域,宏定义是一种预处理指令,常用于C++中的MFC(Microsoft Foundation Classes)框架,它允许程序员创建简短的符号名称来代替复杂的表达式或者代码块。MFC宏定义是C++编程中一个重要的概念,尤其对于构建...
C 中一般使用宏定义“#define”定义常量,而 C++中除此外,建议使用const 代替宏定义,用关键字 const 修饰的标识符称为符号常量。 #### 2.2 预处理程序 C++的预处理程序不是 C++编译程序的一部分,它负责...
MFC 中的宏定义为开发人员提供了强大的工具集,用于简化常见任务,如异常处理、断言检查、消息映射和序列化。这些宏不仅简化了代码编写过程,还提高了代码的可读性和维护性。理解每个宏的功能和用法对于有效地利用 ...
在C语言中,宏定义是预处理器(Preprocessor)的一项重要功能,它允许程序员创建简短的别名或...同时,随着C++的发展,许多宏定义的功能已被模板和 inline 函数所取代,但在某些特定场景下,宏定义仍然是不可或缺的。
宏的`#`和`##`运算符是两个非常特殊的符号,它们在宏定义中起到关键作用。下面将详细解释这两个运算符的工作原理和应用场景。 1. `#` 运算符: `#`被称为字符串化(Stringify)运算符,它将宏参数转换为字符串字面...
根据提供的文件信息,我们可以深入探讨C++中的存储类型修饰符以及与之相关的字符转换方法,尤其是在ANSI与Unicode环境下的转换。尽管标题和描述都简短地提到了“C++存储类型修饰符”,但具体内容涉及了更具体的话题...
宏定义也可以用于条件编译,例如,`#ifndef _AAA_H #define _AAA_H //c/c++代码 #endif`。 注意事项 1. 不能重复定义,除非定义完全相同。 2. 可以只定义符号,不定义值。 #和##在C语言中的作用 #的功能是将其...
在C和C++编程语言中,`##`、`#`、`__VA_ARGS__` 和 `...` 是四个非常特殊的宏操作符,它们在预处理器宏定义中扮演着重要的角色。下面将详细阐述这些概念及其应用。 1. `##` 连接操作符: `##` 操作符用于在宏展开...
定义了预处理器能够识别的标记,如宏定义、条件编译等,这些都是C++预处理的重要组成部分。 ##### 2.5 替代标记 解释了如何用替代标记(alternative tokens)来代替某些难以输入的字符,提高编程效率。 ##### 2.6 ...
### C++宏、预处理器、RTTI、typeid与强制类型转换专题 #### 一、概述 本文档由黄邦勇帅编写,旨在深入探讨C++中的几个重要概念:`sizeof`操作符、预处理器(包括`#define`)、运行时类型识别(RTTI)与`typeid`以及...
- **丰富的特性**:C++不仅包含了C的所有特性,还增加了更多高级功能,如私有和保护成员、函数重载、缺省参数、构造和析构函数、自定义操作符、内联函数、引用、友元、模板、异常处理以及名字空间等。这些新特性使得...
预处理程序是C++编译过程的第一步,它负责处理源代码中的预处理指令,如宏定义、文件包含和条件编译。这些指令以`#`符号开头,通常用于代码的预处理工作,比如替换宏定义、包含其他源文件等。 ### 小结 C++作为一种...
C/C++语言的操作符具有优先级,正确理解操作符的优先级是编写正确程序的关键。ASCII码表是计算机中字符编码的一种标准,它将不同的字符映射为不同的数值,便于计算机处理文本数据。C/C++中的转义字符用于表示一些...
`#`操作符在宏定义中有着特殊的作用,它被称为“字符串化”操作符,可以把一个标识符转换为对应的字符串字面量。这对于在调试或者日志记录时非常有用,因为它允许我们打印出函数名或者其他标识符的文本形式。例如,...