宏定义基本用法
来源:互联网 发布:淘宝上色盲眼镜有用吗 编辑:程序博客网 时间:2024/06/07 03:04
宏定义
不带参数
宏定义又称为宏代换、宏替换,简称“宏”。
格式:
#define 标识符 字符串
其中的标识符就是所谓的符号常量,也称为“宏名”。
预处理(预编译)工作也叫做宏展开:将宏名替换为字符串。
掌握”宏”概念的关键是“换”。一切以换为前提、做任何事情之前先要换,准确理解之前就要“换”。
例:
#define Pi 3.1415926
把程序中出现的Pi全部换成3.1415926
带参数(宏函数)
宏名之后带括号的宏被认为是宏函数。用法和普通函数一样,只不过在预处理阶段,宏函数会被展开。优点是没有普通函数保存寄存器和参数传递的开销,展开后的代码有利于CPU cache的利用和指令预测,速度快。缺点是可执行代码体积大。
和不带参数的宏定义一样,除了一般的字符串替换,还要做参数代换。
格式:
#define <宏名> (<参数表>) <宏体>
例如:
#define S(a,b) a*b
area=S(3,2);第一步被换为area=a * b; ,第二步被换为area=3 * 2;
(1)实参如果是表达式容易出问题
例如:
#define S(r) r*r
area=S(a+b);第一步换为area=r * r;,第二步被换为area=a+b * a+b;
正确的宏定义是#define S(r) ((r)*(r))
(2)带参宏一般用法
例如:
#define MIN(A, B) A < B ? A : Bint a = 2 * MIN(3, 4);printf("%d", a);
展开结果:
int a = 2 * MIN(3, 4);//=> int a = 2 * 3 < 4 ? 3 : 4;//=> int a = 6 < 4 ? 3 : 4;//=> int a = 4;
正确如下:
#define MAX(a,b) ((a)>(b)?(a):(b))
则遇到MAX(1+2,value)则会把它替换成:
((1+2)>(value)?(1+2):(value))
(3)有参宏定义中#的用法
需要注意的是凡宏定义里有用’#’或’##’的地方宏参数是不会再展开,被当做字符串处理
#define STR(str) #str
“#”号用于把宏定义中的参数两端加上字符串的”“
比如,这里 STR(my#name) 会被替换成”my#name”
(4)有参宏定义中##的用法
例如:
#define WIDE(str) L##str
则会将形参str的前面加上L
比如:
WIDE(“abc”)就会被替换成L”abc”
如果有:
#define FUN(a,b) vo##a##b()
那么FUN(id ma,in)会被替换成void main()
多行宏定义
每一次换行都必须要有 “ \ ”结尾,末尾行不需要“ \ ” 结尾。
例如:
#define doit(m,n) for(int i=0;i<(n);++i)\ {\ m+=i;\ }
#define WARN_IF(EXP) \ do { if (EXP) \ fprintf (stderr, "Warning: " #EXP "\n"); } \ while (0)
WARN_IF (x == 0);会被扩展成:
do { if (x == 0) fprintf (stderr, "Warning: " "x == 0" "\n"); }while (0);
#define VAR_TO_STR(var)\ ({\ std::string name = (#var);\ int pos = 0;\ int length = 0;\ length = name.length();\ pos = name.find_last_of(':',length);\ if ( pos == -1 )\ {\ pos = 0;\ name = name.substr(pos,length);\ }\ else\ {\ name = name.substr( pos + 1,length);\ }\ (name);\ })
std::string str = VAR_TO_STR(VDAD::RRR) 展开后:
int main(){ std::string ss =({ std::string name = ("VDAD::RRR"); int pos = 0; int length = 0; length = name.length(); pos = name.find_last_of(':',length); if ( pos == -1 ) { pos = 0; name = name.substr(pos,length); } else { name = name.substr( pos + 1,length); } (name); }); cout << ss<< endl; return 0;}
输出为:
相关链接
1.C语言宏的特殊用法和几个坑
2.C/C++ 宏定义
- 宏定义基本用法
- 宏定义基本用法---【以备不时之需】
- c/c++宏定义的基本用法
- shape基本用法及全部属性定义
- shape基本用法及全部属性定义
- 协议的基本用法和定义
- NSArray 和 NSMutableArray 定义和基本用法
- NSSet 和 NSMutableSet 定义和基本用法
- NSString 和 NSMutableString 定义和基本用法
- shape基本用法及全部属性定义
- 宏定义基本使用
- 宏定义define用法
- #ifndef宏定义用法
- 宏定义用法总结
- 宏定义函数用法
- 宏定义#号用法
- 宏定义-#define用法
- 宏定义用法
- Kruskal和Prim--最小生成树算法
- 10、ES6 字符串的解构赋值
- 编程珠玑记录: 第一天
- 求两个整数的最大公因子 欧几里得算法(辗转相除法)
- 百度万亿量级数据库Tera架构应用、设计与实践全攻略
- 宏定义基本用法
- leetcode 464. Can I Win
- hexo进阶使用
- HTML-css入门简介
- 如何修复Google Chrome上的“ERR_SSL_PROTOCOL_ERROR”
- 关于微服务和 Java 需要知道的 5 件事
- Lintcode:斐波那契数列
- 成功抓取csdn阅读量过万博文
- 通过汇编一个简单的C程序,分析汇编代码理解计算机是如何工作的