#与##在宏定义中的--宏展开
#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
- 浏览: 150687 次
- 性别:
- 来自: 上海
最新评论
-
oyhuang:
看不懂啊,这么多行
麻将胡牌逻辑 java -
墙头上一根草:
最近项目在上线 所以好久没上来了 这个确实是我研究不够透彻 ...
mybatis中不能出现小于号 -
Tyrion:
...不是说不支持“<”而是因为你用的是xml文件配置, ...
mybatis中不能出现小于号 -
add2ws:
小于和大于号和xml里的尖括号冲突,应该用<和& ...
mybatis中不能出现小于号 -
hellotieye:
楼主 mybatis 是可以使用小于号的 再好好学一下 没关系 ...
mybatis中不能出现小于号
相关推荐
C++操作符重载 实现效果图: 实例代码: Matrix.h #pragma once #include "vector" #include "iostream" #define rep(i,n) for(int i=1;i<=n;i++) //宏定义for循环,精简代码 using namespace std; class ...
本资源摘要信息涵盖了C++编程语言的多个方面,包括预处理指令、宏定义、条件操作符、三重条件操作符、嵌入式系统、死循环、数据声明等。 1. 预处理指令#define 在C++编程语言中,预处理指令#define用于声明常数。...
14.2.1 派生类中的赋值操作符和复制 构造函数 426 14.2.2 派生类的析构函数 426 14.2.3 保护继承和私有继承 436 14.2.4 多继承 437 第15章 多态与虚函数 442 15.1 虚函数基础 442 15.1.1 后绑定 442 15.1.2 ...
18第2章 保证稳定性和兼容性 192.1 保持与C99兼容 192.1.1 预定义宏 192.1.2 __func__预定义标识符 202.1.3 _Pragma操作符 222.1.4 变长参数的宏定义以及__VA_ARGS__ 222.1.5 宽窄字符串的连接 232.2 long long整型 ...
头文件中只能包含宏定义、函数声明和变量声明,不允许包含函数实现和变量定义。 * 定义文件(.CPP/.C):定义文件用于实现函数和变量的定义。定义文件的名称通常与头文件相同,但以小写字母开头,例如myheader.cpp。 *...
0065 如何重载操作符 27 0066 如何定义重载函数 28 0067 默认构造函数 28 0068 复制构造函数 28 0069 this指针分析 29 0070 如何用非静态的类成员函数作为线程函数 29 0071 如何在常量函数中修改数据...
(1)new、delete是操作符,可以重载,只能在C++中使用。 (2)malloc、free是函数,可以覆盖,C、C++中都可以使用。 (3)new可以调用对象的构造函数,对应的delete调用相应的析构函数。 (4)malloc仅仅分配内存,...
宏定义 SQR(X) X*X 只是简单的代换 X*X,而不经过算术法则的计算。因此,a /= SQR(k+m)/SQR(k+m); 等价于 a /= (k+m)*(k+m)/(k+m)*(k+m); => a /= (k+m)*1*(k+m); => a = a/9; => a = 1; 5. const 符号常量; ...
第27条 优先使用算术操作符和赋值操作符的标准形式 48 第28条 优先使用++和--的标准形式。优先调用前缀形式 50 第29条 考虑重载以避免隐含类型转换 51 第30条 避免重载&&、||或 ,(逗号) 52 第31条 ...
4.1 关系操作符、相等操作符和逻辑操作符 4.2 关系操作符和表达式 4.3 相等操作符和表达式 4.4 逻辑操作符和表达式 4.5 复合语句 4.6 表达式和空语句 4.7 if和if-else语句 4.8 while语句 4.9 for语句 4.10 例子:...
9.2.1 无参宏定义 126 9.2.2 带参宏定义 127 9.3 文件包含 128 9.4 条件编译 130 9.5 本章小结 10 指针 10.1 地址指针的基本概念 131 10.2 变量的指针和指向变量的指针变量 132 10.2.1 定义一个指针变量 133 10.2.2 ...
学习 Linux 下 C++ 开发可以提高编程效率、灵活性和可维护性,同时也能够让开发者更好地理解操作系统和计算机硬件。 G++ 简介与实例 G++ 是 Linux 下的 C/C++ 编译器,能够将源代码编译成可执行文件。G++ 的基本...
13.1 使用格式操作符设置输出格式 13.2 输出格式设置间的交互作用 13.3 3 种格式设置语法的比较 13.4 文件存储格式的设置 13.5 矩阵和向量间的操作 13.6 常犯的错误 13.7 本章重点 13.8 本章练习 第14章 ...
面试题3:流操作符重载为什么返回引用 5.2 指针 面试题4:说明以下声明的含义 面试题5:简述指针常量与常量指针区别 面试题6:写出以下代码的输出结果 面试题7:找出代码的错误 5.3 指针和数组 面试题8:写出代码的...
c++面试题53个问题 1.C++的三大特性 2.C和C++的区别 ...49.sizeof是一个操作符,strlen是库函数 50.写一个“标准”宏MIN 51.简述strcpy sprintf与mencpy的区别 52.链表与数组的区别 53.简述队列和栈的异同
在C++语言中,使用 #define 宏来定义常量或函数是非常危险的,因为宏的行为不可预测且难以调试。因此,宁以 const,inline,enum 等机制代替 #define,以提高代码的可读性和可维护性。 31.3 尽可能使用 const 在...