#define是C语言中提供的宏定义命令:
用来将一个标识符定义为一个字符串,该标识符被称为宏名,被定义的字符串称为替换文本。
#define<宏名> <字符串>
#define<宏名> (<参数表>)<宏体>
宏展开是在预处理阶段完成的,这个阶段把替换文本只是看作一个字符串,并不会有任何的计算发生
#define中的三个特殊符号:#,##,#@
- #define Cat(x,y) x##y //token-pasting 符号连接操作符
- #define ToChar(x)#@x // charizing 字符化操作符
- #define ToString(x)#x // stringizing 字符串化操作符
ANSI标准说明了五个预定义的宏名。它们是:
- _LINE_ /*(两个下划线),对应%d*/
- _FILE_ /*对应%s*/
- _DATE_ /*对应%s*/
- _TIME_ /*对应%s*/
用#pragma导出DLL函数
__declspec(dllexport) //导出函数
__declspec(dllimport) //申明导入函数
重命名导出函数
#pragma comment(linker,"/EXPORT:MyExportFunction=_MyExportFunction@4")
/EXPORT:entryname[,@ordinal[,NONAME]][,DATA]
@ordinal 指定顺序;NONAME 指定只将函数导出为序号;DATA 关键字指定导出项为数据项。
@ordinal 指定顺序;NONAME 指定只将函数导出为序号;DATA 关键字指定导出项为数据项。
指定链接库
#pragma comment(lib, "WSock32.lib")
#pragma warning( disable : 4507 34; once : 4385; error : 164 ) //编译器忽略4507 和34, 仅报告1次4385 把164警告作为错误。
#pragma message(“消息文本”) //当编译器遇到这条指令时就在编译输出窗口中将消息文本打印出来。
另一个使用得比较多的pragma参数是code_seg。格式如:
#pragma code_seg( ["section-name"[,"section-class"] ] )
它能够设置程序中函数代码存放的代码段,当我们开发驱动程序的时候就会使用到它。
#pragma once (比较常用)
#pragma code_seg( ["section-name"[,"section-class"] ] )
它能够设置程序中函数代码存放的代码段,当我们开发驱动程序的时候就会使用到它。
#pragma once (比较常用)
#pragma hdrstop表示预编译头文件到此为止,后面的头文件不进行预编译。
#pragma resource "*.dfm"表示把*.dfm文件中的资源加入工程。
常用的一些宏定义
1 防止一个头文件被重复包含
- #ifndef BODYDEF_H
- #define BODYDEF_H
- //头文件内容
- #endif
2 得到指定地址上的一个字节或字
- #define MEM_B( x) ( *( (byte*) (x) ))
- #define MEM_W( x) ( *( (word*) (x) ))
- int main()
- {
- int bTest = 0x123456;
- byte m = MEM_B((&bTest));/*m=0x56*/
- int n = MEM_W((&bTest));/*n=0x3456*/
- return 0;
- }
3 得到一个field在结构体(struct)中的偏移量
- #defineOFFSETOF( type, field) ( (size_t) &(( type*) 0)-> field)
得到一个field在结构体(struct type)中的偏移量
- #define OFFSETOF(type, field) ((size_t)&(((type *)0)->field))
-
- (type *)0:把0地址当成type类型的指针。
-
- ((type *)0)->field:对应域的变量。
-
- &((type *)0)->field:取该变量的地址,其实就等于该域相对于0地址的偏移量。
-
- (size_t)&(((type *)0)->field):将该地址(偏移量)转化为size_t型数据。
ANSI C标准允许任何值为0的常量被强制转换成任何一种类型的指针,并且转换结果是一个NULL指针,因此((s*)0)的结果就是一个类型为s*的NULL指针。如果利用这个NULL指针来访问s的成员当然是非法的,但&(((s*)0)->m)的意图并非想存取s字段内容,而仅仅是计算当结构体实例的首址为((s*)0)时m字段的地址。聪明的编译器根本就不生成访问m的代码,而仅仅是根据s的内存布局和结构体实例首址在编译期计算这个(常量)地址,这样就完全避免了通过NULL指针访问内存的问题。
注:
1. 有人这样表达:
- #define OFFSETOF(type, field) ((size_t) \
- ((char *)&((type *)0)->field - (char *)(type *)0))
4 得到一个结构体中field所占用的字节数
- #define FSIZ( type, field) sizeof(((type *) 0)->field)
5 得到一个变量的地址(word宽度)
- #define B_PTR( var) ( (byte *)(void *) &(var))
- #define W_PTR( var) ( (word *)(void *) &(var))
6 将一个字母转换为大写
- #define UPCASE( c) ( ((c)>= ''a'' &&(c) <= ''z'')? ((c)- 0x20) : (c))
7 判断字符是不是10进值的数字
- #define DECCHK( c) ((c)>= ''0'' &&(c) <= ''9'')
8 判断字符是不是16进值的数字
- #define HEXCHK( c) ( ((c)>= ''0'' &&(c) <= ''9'')||((c)>= ''A'' &&(c) <= ''F'')||((c)>= ''a'' &&(c) <= ''f''))
9 防止溢出的一个方法
- #define INC_SAT( val) (val = ((val)+1> (val))? (val)+1: (val))
10 返回数组元素的个数
- #define ARR_SIZE( a) ( sizeof( (a)) / sizeof( (a[0])) )
#define DECVAL_1 0
#define DECVAL_2 1
#define DECVAL_3 2
#define DECVAL_4 3
#define DECVAL_5 4
#define DECVAL_6 5
#define DECVAL_7 6
#define DECVAL_8 7
#define DECVAL_9 8
#define DECVAL( n ) DECVAL_##n
#define DECVAL_2 1
#define DECVAL_3 2
#define DECVAL_4 3
#define DECVAL_5 4
#define DECVAL_6 5
#define DECVAL_7 6
#define DECVAL_8 7
#define DECVAL_9 8
#define DECVAL( n ) DECVAL_##n
参考:
http://blog.csdn.net/witch_soya/article/details/7645493
http://blog.chinaunix.net/uid-21372424-id-120086.html