#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