C/C++宏定义 摘抄


 #define是C语言中提供的宏定义命令:

用来将一个标识符定义为一个字符串,该标识符被称为宏名,被定义的字符串称为替换文本。

#define<宏名>  <字符串>

#define<宏名> (<参数表>)<宏体>

宏展开是在预处理阶段完成的,这个阶段把替换文本只是看作一个字符串,并不会有任何的计算发生

#define中的三个特殊符号:#,##,#@

  1. #define Cat(x,y) x##y                //token-pasting 符号连接操作符
  2. #define ToChar(x)#@x                // charizing 字符化操作符
  3. #define ToString(x)#x                  // stringizing 字符串化操作符


ANSI标准说明了五个预定义的宏名。它们是: 
  1. _LINE_ /*(两个下划线),对应%d*/
  2. _FILE_ /*对应%s*/
  3. _DATE_ /*对应%s*/
  4. _TIME_ /*对应%s*/


用#pragma导出DLL函数
__declspec(dllexport)  //导出函数
__declspec(dllimport)  //申明导入函数

重命名导出函数
#pragma comment(linker,"/EXPORT:MyExportFunction=_MyExportFunction@4")
/EXPORT:entryname[,@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 hdrstop表示预编译头文件到此为止,后面的头文件不进行预编译。

#pragma resource "*.dfm"表示把*.dfm文件中的资源加入工程。

常用的一些宏定义

1 防止一个头文件被重复包含 
  1. #ifndef BODYDEF_H
  2. #define BODYDEF_H
  3.  //头文件内容 

  4. #endif
 
2 得到指定地址上的一个字节或字

  1. #define MEM_B( x) ( *( (byte*) (x) )) 
  2. #define MEM_W( x) ( *( (word*) (x) ))
例子:
  1. int main()
  2. {
  3.     int bTest = 0x123456;

  4.     byte m = MEM_B((&bTest));/*m=0x56*/
  5.     int n = MEM_W((&bTest));/*n=0x3456*/
  6.     return 0;
  7. }
3 得到一个field在结构体(struct)中的偏移量
 
  1. #defineOFFSETOF( type, field) ( (size_t) &(( type*) 0)-> field)
 

得到一个field在结构体(struct type)中的偏移量

  1. #define OFFSETOF(type, field) ((size_t)&(((type *)0)->field))

  2. (type *)0:把0地址当成type类型的指针。

  3. ((type *)0)->field:对应域的变量。

  4. &((type *)0)->field:取该变量的地址,其实就等于该域相对于0地址的偏移量。

  5. (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. 有人这样表达:

  1. #define OFFSETOF(type, field) ((size_t) \
  2.     ((char *)&((type *)0)->field - (char *)(type *)0))

4 得到一个结构体中field所占用的字节数 
  1. #define FSIZ( type, field) sizeof(((type *) 0)->field)

5 得到一个变量的地址(word宽度) 
  1. #define B_PTR( var) ( (byte *)(void *) &(var)) 
  2. #define W_PTR( var) ( (word *)(void *) &(var))
6 将一个字母转换为大写

  1. #define UPCASE( c) ( ((c)>= ''a'' &&(c) <= ''z'')? ((c)- 0x20) : (c))
7 判断字符是不是10进值的数字

  1. #define DECCHK( c) ((c)>= ''0'' &&(c) <= ''9'')
8 判断字符是不是16进值的数字 
  1. #define HEXCHK( c) ( ((c)>= ''0'' &&(c) <= ''9'')||((c)>= ''A'' &&(c) <= ''F'')||((c)>= ''a'' &&(c) <= ''f''))
9 防止溢出的一个方法

  1. #define INC_SAT( val) (val = ((val)+1> (val))? (val)+1: (val))
10 返回数组元素的个数 
  1. #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

参考:
http://blog.csdn.net/witch_soya/article/details/7645493
http://blog.chinaunix.net/uid-21372424-id-120086.html


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值