C define详解
1.简单的define定义
#define MAXTIME 1000
一个简单的MAXTIME就定义好了,它代表1000,如果在程序里面写
if(i<MAXTIME){.........}
编译器在处理这个代码之前会对MAXTIME进行处理替换为1000。
这样的定义看起来类似于普通的常量定义CONST,但也有着不同,因为define的定义只是简单的文本替换,并不做类型检查,这个问题在下面反映的尤为突出。
2.define的“函数定义”
define可以像函数那样接受一些参数,如下
#define max(x,y) (x)>(y)?(x):(y);
这个定义就将返回两个数中较大的那个,看到了吗?因为这个“函数”没有类型检查,就好像一个函数模板似的,当然,它绝对没有模板那么安全就是了。可以作为一个简单的模板来使用而已。
但是这样做的话存在隐患,例子如下:
#define Add(a,b) a+b;
在一般使用的时候是没有问题的,但是如果遇到如:c * Add(a,b) * d的时候就会出现问题,代数式的本意是a+b然后去和c,d相乘,但是因为使用了define(它只是一个简单的替换),所以式子实际上变成了
c*a + b*d
另外举一个例子:
#define pin (int*);
pin a,b;
本意是a和b都是int型指针,但是实际上变成int* a,b;
a是int型指针,而b是int型变量。
这时应该使用typedef来代替define,这样a和b就都是int型指针了。
所以我们在定义的时候,养成一个良好的习惯,建议所有的层次都要加括号。
3.宏定义中的特殊操作符
define 中的特殊操作符有#,##和 ... and __VA_ARGS__
(1) #
假如希望在字符串中包含宏参数,ANSI C允许这样做,在类函数宏的替换部分,#符号用作一个预处理运算符,它可以把语言符号转换成字符串。例如,如果x是一个宏参量,那么#x可以把参数名转换成相应的字符串,该过程称为字符串化。
代码示例:
#incldue <stdio.h> #define PSQR(x) printf("the square of "#x" is %d.\n",(x)*(x)) int main(void) { int y =4; PSQR(y); //输出:the square of y is 16. PSQR(2+4); //输出:the square of 2+4 is 36. return 0; }
(2)##
##运算符可以用于类函数宏的替换部分。另外,##还可以用于类对象宏的替换部分。这个运算符把两个语言符号组合成单个语言符号。
代码示例:
#include <stdio.h> #define XNAME(n) x##n #define PXN(n) printf("x"#n" = %d\n",x##n) int main(void) { int XNAME(1)=12;//int x1=12; PXN(1);//printf("x1 = %d\n", x1); //输出:x1=12 return 0; }
(3)可变参数宏 ... 和 __VA_ARGS__
__VA_ARGS__ 是一个可变参数的宏,这个可变参数的宏是新的C99规范中新增的,目前似乎只有gcc支持。
实现思想就是宏定义中参数列表的最后一个参数为省略号(也就是三个点)。这样预定义宏__VA_ARGS__就可以被用在替换部分中,替换省略号所代表的字符串。
代码示例:
#define PR(...) printf(__VA_ARGS__) int main() { int wt=1,sp=2; PR("hello\n"); //输出:hello PR("weight = %d, shipping = %d",wt,sp); //输出:weight = 1, shipping = 2 return 0; }
省略号只能代替最后面的宏参数。
#define W(x, ..., y) 错误!
#define W(x, ...) 正确!此时传入的参数个数必须能够匹配。
这里再介绍其它几个系统的宏:
1)__FILE__ 宏在预编译时会替换成当前的源文件名
2)__LINE__ 宏在预编译时会替换成当前的行号
3)__FUNCTION__ 宏在预编译时会替换成当前的函数名称
4.define的多行定义
define可以替代多行的代码,例如MFC中的宏定义
#define MACRO(arg1, arg2) do { /
/* declarations */ /
stmt1; /
stmt2; /
/* ... */ /
} while(0) /* (no trailing ; ) */
关键是要在每一个换行的时候加上一个"/"
5.在大规模的开发过程中,特别是跨平台和系统的软件里,define最重要的功能是条件编译
就是:
#ifdef WINDOWS
......
......
#endif
#ifdef LINUX
......
......
#endif
可以在编译的时候通过#define设置编译环境
6.如何定义宏、取消宏
//定义宏
#define [MacroName] [MacroValue]
//取消宏
#undef [MacroName]
7.条件编译
#ifdef XXX…(#else) …#endif
#ifndef XXX...(#else)...#endif
例如
#ifdef DV22_AUX_INPUT
#define AUX_MODE 3
#else
#define AUY_MODE 3
#endif
8.头文件(.h)可以被头文件或C文件包含
重复包含(重复定义)
由于头文件包含可以嵌套,那么C文件就有可能包含多次同一个头文件,就可能出现重复定义的问题的。
通过条件编译开关来避免重复包含(重复定义)
例如
#ifndef __headerfileXXX__
#define __headerfileXXX__
…
文件内容
…
#endif
参考:https://blog.csdn.net/lyl_98/article/details/900158