宏定义 #define
宏定义能够在代码中直接替换相关的内容,恰当地使用可以提高程序的执行效率,提高程序的清晰度和可读性,提供了一种复用方式(否则都得用函数编写),省去了分配和释放栈帧、传参、传返回值等一系列工作, 但是大量使用也会造成代码可读性下降。
常用宏定义命令
命令 | 解释 |
---|---|
define | 定义一个预处理宏 |
undef | 取消宏的定义 |
include | 包含文件命令 |
include_next | 与#include相似, 但它有着特殊的用途 |
if | 编译预处理中的条件命令, 相当于C语法中的if语句 |
ifdef | 判断某个宏是否被定义, 若已定义, 执行随后的语句 |
ifndef | 与#ifdef相反, 判断某个宏是否未被定义 |
elif | 若#if, #ifdef, #ifndef或前面的#elif条件不满足, 则执行#elif之后的语句, 相当于C语法中的else-if |
else | 与#if, #ifdef, #ifndef对应, 若这些条件不满足, 则执行#else之后的语句, 相当于C语法中的else |
endif | if, #ifdef, #ifndef这些条件命令的结束标志. |
defined | 与#if, #elif配合使用, 判断某个宏是否被定义 |
line | 标志该语句所在的行号 |
“#” | 将宏参数替代为以参数值为内容的字符窜常量 |
“##” | 将两个相邻的标记(token)连接为一个单独的标记 |
pragma | 说明编译器信息 |
warning | 显示编译警告信息 |
error | 显示编译错误信息 |
其中 ## 表示连接两个字符, # 表示将参数字符串化
不带参宏定义
例如: #define MAX 1000
(1)宏名一般用大写
(2)使用宏可提高程序的通用性和易读性,减少不一致性,减少输入错误和便于修改。例如:数组大小常用宏定义
(3)预处理是在编译之前的处理,而编译工作的任务之一就是语法检查,预处理不做语法检查。
(4)宏定义末尾不加分号;
(5)宏定义写在函数的花括号外边,作用域为其后的程序,通常在文件的最开头。
(6)可以用#undef命令终止宏定义的作用域
(7)宏定义可以嵌套
(8)字符串" "中永远不包含宏
带参的宏定义
例如:#define ADD(x,y) ((x)+(y))
1)实参如果是表达式容易出问题
#define S(r) r*r
area=S(a+b);第一步换为area=r*r;,第二步被换为area=a+b*a+b;
正确的宏定义是#define S(r) (r)*(r)
(2)宏名和参数的括号间不能有空格
(3)宏替换只作替换,不做计算,不做表达式求解
(4)函数调用在编译后程序运行时进行,并且分配内存。宏替换在编译前进行,不分配内存
(5)宏的哑实结合不存在类型,也没有类型转换。
(6)函数只有一个返回值,利用宏则可以设法得到多个值
(7)宏展开使源程序变长,函数调用不会
(8)宏展开不占运行时间,只占编译时间,函数调用占运行时间(分配内存、保留现场、值传递、返回值)
(9)宏定义不分配内存,变量定义分配内存。宏替换发生的过程
宏函数
//此函数会一直打印 “hello”
#include<stdio.h>
#define FOO(str)printf("%s",str);
#define FUN1(i)do{printf("hello");}while (i)
#define FUN2(i)for (;i;){printf("hello");}
int main(void)
{
FOO("hello");
if (3)
{
FUN2(2)
}
else
FUN1(0);
getchar();
return 0;
}
#pragma
去除4127号警告 #pragma warning(disable:4127)
使用示例
#define forEachAs( listtype, list, iter ) \
for ( listtype::iterator iter = (list)->begin(); iter != (list)->end(); ++iter )
#define ADD(a,b) (a+b)