#define简单总结
C primer plus 第十六章
Definition:
The #define Directive
You can use the #define directive to give a meaningful name to a constant in your program. The two forms of the syntax are:
Syntax
#define identifier token-stringopt
#define identifier[( identifieropt, ... , identifieropt )] token-stringopt
##明示常量
#define Pi 3.14
#define PX printf("X is %d.\n", x)
##在#define中使用参数
#define SQUARE(X) X*X /*SQAURE(x+2) --> x+2*x+2*/
#define SQUARE(X) (X)*(X) /*100/SQUARE(2) --> 100/(2)*(2)*/
#define SQUARE(X) ((X)*(X)) /*SQUARE(++x) --> 视编译器不同可能得出不同的结果, 如结果等于(x+1)*(x+2)或者(x+2)*(x+2) 所以尽量避免在宏定义中使用++x*/
##用宏参数创建字符串: #运算符
#define PSQR(x) printf("The square of " #x " is %d.\n",((x)*(x)))
int main(void)
{ 
	int y = 5;
	PSQR(y);
	PSQR(2 + 4);
	return 0;
}
输出如下:
The square of y is 25.
The square of 2 + 4 is 36.
调用第一个宏的时候, 用"y"替换#x. 调用第二个宏的时候, 用"2 + 4"替换#x. ANSI C 字符串的串联特性将这些字符串与printf()语句的其它字符串组合, 生成最终的字符串. 例如, 第一次调用变为:
printf("The square of " "y" " is %d.\n", ((y)(y)));
然后, 字符串串联功能将这3个相邻的字符串组合成一个字符串:
"The square of y is %d.\n"
#undef指令
#define LIMIT 100
/*
a lot of codes
*/
#undef LIMIT //就是取消已定义的LIMIT
有些预定义的宏是不能取消的, 如__DATE__等
##常用的#define语句
- 
得到指定地址上的一个字节或字 #define MEM_B(x) ( *( (byte *) (x) ) ) #define MEM_W(x) ( *( (word *) (x) ) )
- 
求最大值和最小值 #define MAX(x,y) ( ((x) > (y)) ? (x) : (y) ) #define MIN(x,y) ( ((x) < (y)) ? (x) : (y) )
- 
得到一个field在结构体(struct)中的偏移量 #define FPOS(type, field) / /*lint -e545 */ ( (dword) &(( type *) 0)-> field ) /*lint +e545 */
- 
得到一个结构体中field所占用的字节数 #define FSIZ(type, field) sizeof( ((type *) 0)->field )
- 
按照LSB格式把两个字节转化为一个Word #define FLIPW(ray) ( (((word) (ray)[0]) * 256) + (ray)[1] )
- 
得到一个变量的地址(word宽度) #define B_PTR(var) ( (byte *) (void *) &(var) ) #define W_PTR(var) ( (word *) (void *) &(var) )
- 
得到一个字的高位和低位字节 #define WORD_LO(xxx) ((byte) ((word)(xxx) & 255)) #define WORD_HI(xxx) ((byte) ((word)(xxx) >> 8))
- 
返回一个比X大的最接近的8的倍数 #define RND8(x) ((((x) + 7) / 8 ) * 8 )
- 
将一个字母转换为大写 #define UPCASE(c) ( ((c) >= 'a' && (c) <= 'z') ? ((c) - 0x20) : (c))
- 
判断字符是不是10进值的数字 #define DECCHK(c) ((c) >= '0' && (c) <= '9')
- 
判断字符是不是16进值的数字 #define HEXCHK(c) ( ((c) >= '0' && (c) <= '9') ||/ ((c) >= 'A' && (c) <= 'F') ||/ ((c) >= 'a' && (c) <= 'f') )
- 
防止溢出的一个方法 #define INC_SAT(val) (val = ((val)+1 > (val)) ? (val)+1 : (val))
- 
返回数组元素的个数 #define ARR_SIZE(a) ( sizeof( (a) ) / sizeof( (a[0]) ) )
- 
返回一个无符号数n尾的值MOD_BY_POWER_OF_TWO(X,n)=X%(2^n) #define MOD_BY_POWER_OF_TWO(val,mod_by) / ( (dword)(val) & (dword)((mod_by)-1) )
- 
对于IO空间映射在存储空间的结构,输入输出处理 #define inp(port) (*((volatile byte *) (port))) #define inpw(port) (*((volatile word *) (port))) #define inpdw(port) (*((volatile dword *)(port))) #define outp(port, val) (*((volatile byte *) (port)) = ((byte) (val))) #define outpw(port, val) (*((volatile word *) (port)) = ((word) (val))) #define outpdw(port, val) (*((volatile dword *) (port)) = ((dword) (val)))
- 
#define中的特殊标识符 #define Conn(x,y) x##y #define ToChar(x) #@x #define ToString(x) #x int a=Conn(12,34);//a=1234, ##是连接 char b=ToChar(a);//b='a', #@用来给参数加单引号 char c[]=ToString(a);//c="1234", #用来给参数加双引号
- 
LOG日志与do{}while(0) #include <stdio.h> #include <stdlib.h> #define BUFSIZE 1024 #define LOG(str) \ do \ {\ fprintf(stderr, "[%s:%d %s %s]:%s\r\n", __FILE__, __LINE__, __DATE__, __TIME__, str); \ }while(0) int main() { char *buf = (char *)malloc(BUFSIZE); LOG("malloc for buf"); free(buf); return 0; }
输出为: [macro.c:12 Jan 13 2019 22:38:33]:malloc for buf
