#define 是宏命令,预处理指令,在编译前,由预处理器做简单替代(如同文本编辑的替代命令,把程序中的所有遇到的词,全部替代),不作正确性检查,不管含义是否正确照样带入,只有在编译已被展开的源程序时才会发现可能的错误并报错。
#define 不是语句,不要在行末加分号,否则会连分号一块置换。
如何定义宏、取消宏 (句末不带分号)
#define [Name] [Value] //定义宏
#undef [Name] //取消宏
#define PI (3.1415926) //普通宏
#define max(a,b) ((a)>(b)? (a),(b)) //带参数的宏
1.简单的define定义
#define DATA 1000 //一个简单的DATA定义,它代表1000
if(i<DATA){.........} //编译器在编译时,将DATA替换为1000。
这样的定义看起来类似于普通的常量定义CONST,但也有着不同,因为define的定义更像是简单的文本替换,而不是作为一个量来使用,这个问题在下面反映的尤为突出。
2.define的“函数定义”
define可以像函数那样接受一些参数,如下
#define max(x,y) (x)>(y)?(x):(y) //若句末带分号,后面执行count<<"max:"<<(max(a,b))<<endl;会报错误。
因为这个“函数”没有类型检查,就好像一个函数模板似的,当然,它绝对没有模板那么安全就是了。可以作为一个简单的模板来使用而已。
但是这样做的话存在隐患,例子如下:
(1)#define Add(a,b) a+b
遇到c * Add(a,b) * d时,对Add(a,b)进行简单替换,式子为:c*a + b*d
(2)#define pin (int*)
pin a,b; //替换后为int* a,b;
本意是a和b都是int型指针,但实际为:a是int型指针,而b是int型变量。此时应该使用typedef来代替define,这样a和b就都是int型指针了。
定义时养成一个良好的习惯,建议所有的层次都要加括号。
define可以替代多行的代码,例如MFC中的宏定义:
#define MACRO(arg1, arg2) do { \
/* declarations */ \
stmt1; \
stmt2; \
/* ... */ \
} while(0) /* (no trailing ; ) */
关键是要在每一个换行的时候加上一个"\"
摘抄自http://www.blog.edu.cn/user1/16293/archives/2005/115370.shtml 修补了几个bug
3.define条件编译
#ifdef XXX…(#else) …#endif
#ifndef XXX … (#else) … #endif
例如
#ifdef DV22_AUX_INPUT
#define AUX_MODE 3
#else
#define AUY_MODE 3
#endif
在大规模的开发过程中,特别是跨平台和系统的软件里,define最重要的功能是条件编译。
1 #ifdef WINDOWS
2 ......
3 ......
4 #endif
5 #ifdef LINUX
6 ......
7 ......
8 #endif
可以在编译的时候通过#define设置编译环境 。
关键是十分容易产生错误,包括机器和人理解上的差异等等。
4.define避免重复包含
重复包含(重复定义) 由于头文件包含可以嵌套,那么C文件就有可能包含多次同一个头文件,就可能出现重复定义的问题的。
通过条件编译开关来避免重复包含(重复定义)
例如
#ifndef __headerfileXXX__
#define __headerfileXXX__
…
文件内容
…
#endif