C程序设计语言--宏定义

1.防止一个头文件被重复包含 
[cpp]   viewplain copy print ?
  1. #ifndef COMDEF_H   
  2. #define COMDEF_H   
  3. //头文件内容   
  4. #endif   

 

2.重新定义一些类型,防止由于各种平台和编译器的不同,而产生的类型字节数差异,方便移植。 

[cpp]   viewplain copy print ?
  1. typedef  unsigned char      boolean;        
  2. typedef  unsigned long int  uint32;         
  3. typedef  unsigned short     uint16;         
  4. typedef  unsigned char      uint8;          
  5. typedef  signed long int    int32;          
  6. typedef  signed short       int16;          
  7. typedef  signed char        int8;           


3. 得到指定地址上的一个字节或字 

[cpp]   viewplain copy print ?
  1. #define  MEM_B(  *( (int8 *) (x)   
  2. #define  MEM_W(  *( (uint16 *) (x)   


4. 求最大值和最小值 
    会存在Duplication of SideEffects问题。这里的SideEffect是指宏在展开的时候对其参数可能进行多次Evaluation(也就是取值),但是如果这个宏参数是一个函数,那么就有可能被调用多次从而达到不一致的结果,甚至会发生更严重的错误。比如:
[cpp]   viewplain copy print ?
  1. #define  MAX( x, ((x) (y)) (x) (y)   
  2. #define  MIN( x, ((x) (y)) (x) (y)   
  3. min(a,foo(b));  
这时foo()函数就被调用了两次。为了解决这个潜在的问题,我们应当这样写min(X,Y)这个宏:
[cpp]   viewplain copy print ?
  1. #define min(X,Y) ({\  
  2. typeof (X) x_ (X);\  
  3. typeof (Y) y_ (Y);\  
  4. (x_ y_) x_ y_; })  
({...})的作用是将内部的几条语句中最后一条的值返回,它也允许在内部声明变量(因为它通过大括号组成了一个局部Scope)

5,得到一个field在结构体(struct)中的偏移量 
[cpp]   viewplain copy print ?
  1. #define FPOS( type, field (dword) &(( type *) 0)-> field )  

6,得到一个结构体中field所占用的字节数 
[cpp]   viewplain copy print ?
  1. #define FSIZ( type, field sizeof( ((type *) 0)->field   

7,按照LSB格式把两个字节转化为一个Word 
[cpp]   viewplain copy print ?
  1. #define  FLIPW( ray (((word) (ray)[0]) 256) (ray)[1]   

8,按照LSB格式把一个Word转化为两个字节 
[cpp]   viewplain copy print ?
  1. #define   FLOPW( ray, val   
  2. "white-space:pre" (ray)[0] ((val) 256);   
  3. "white-space:pre" (ray)[1] ((val) 0xFF)   

9,得到一个变量的地址(word宽度) 
[cpp]   viewplain copy print ?
  1. #define  B_PTR( var  (int8 *) (void *) &(var)   
  2. #define  W_PTR( var  (uint16 *) (void *) &(var)   

10,得到一个字的高位和低位字节 
[cpp]   viewplain copy print ?
  1. #define  WORD_LO(xxx)  ((byte) ((uint16)(xxx) 255))   
  2. #define  WORD_HI(xxx)  ((byte) ((uint16)(xxx) >> 8))   

11,返回一个比X大的最接近的8的倍数 
[cpp]   viewplain copy print ?
  1. #define RND8(       ((((x) 7)   

12,将一个字母转换为大写 
[cpp]   viewplain copy print ?
  1. #define  UPCASE( ((c) >= ''a'' && (c) <= ''z'') ((c) 0x20) (c) )  

13,判断字符是不是10进值的数字 
[cpp]   viewplain copy print ?
  1. #define  DECCHK( ((c) >= ''0'' && (c) <= ''9'')   

14,判断字符是不是16进值的数字 
[cpp]   viewplain copy print ?
  1. #define  HEXCHK( ((c) >= ''0'' && (c) <= ''9'') ||\   
  2.                        ((c) >= ''A'' && (c) <= ''F''||\   
  3.                ((c) >= ''a'' && (c) <= ''f''  

15,防止溢出的一个方法 
[cpp]   viewplain copy print ?
  1. #define  INC_SAT( val  (val ((val)+1 (val)) (val)+1 (val))   

16,返回数组元素的个数 
[cpp]   viewplain copy print ?
  1. #define  ARR_SIZE(  sizeof( (a) sizeof( (a[0])   

17,返回一个无符号数n尾的值

MOD_BY_POWER_OF_TWO(X,n)=X%(2^n) 

[cpp]   viewplain copy print ?
  1. #define MOD_BY_POWER_OF_TWO( val, mod_by   
  2.            (dword)(val) (dword)((mod_by)-1)   

18,对于IO空间映射在存储空间的结构,输入输出处理 
[cpp]   viewplain copy print ?
  1. #define inp(port)         (*((volatile byte *) (port)))   
  2. #define inpw(port)        (*((volatile word *) (port)))   
  3. #define inpdw(port)       (*((volatile dword *)(port)))   
  4. #define outp(port, val)   (*((volatile byte *) (port)) ((byte) (val)))   
  5. #define outpw(port, val)  (*((volatile word *) (port)) ((word) (val)))   
  6. #define outpdw(port, val) (*((volatile dword *) (port)) ((dword) (val)))   

 


19. 使用一些宏跟踪调试 
ANSI标准说明了五个预定义的宏名。它们是: 
_LINE_
_FILE_ 
_DATE_ 
_TIME_ 
_STDC_ 
如果编译不是标准的,则可能仅支持以上宏名中的几个,或根本不支持。记住编译程序也许还提供其它预定义的宏名。 
_LINE_标识当前代码所在的行号
_FILE_标识代码所在的文件名
_DATE_宏指令含有形式为月/日/年的串,表示源文件被翻译到代码时的日期。 
源代码翻译到目标代码的时间作为串包含在_TIME_中。串形式为时:分:秒。 
如果实现是标准的,则宏_STDC_含有十进制常量1。如果它含有任何其它数,则实现是非标准的。 

可以定义宏,例如: 
当定义了_DEBUG,输出数据信息和所在文件所在行 
#ifdef _DEBUG   
#define DEBUGMSG(msg,date) printf(msg);printf(“%d%d%d”,date,_LINE_,_FILE_)   
#else   
#define DEBUGMSG(msg,date)   
#endif 
 


C语言中的宏定义

C语言中的宏定义也叫做预处理命令,预处理命令是C语言本身的组成部分,不能直接对它们进行编译。

1.基本概念;

1>预处理不是C语句,是在编译前进行的

2>预处理功能主要用于下3种情况:

Ø  宏定义

Ø  文件包含

Ø  条件编译

3>宏是在编译前进行的,程序不能直接对它们进行编译,由预处理程序先进行替换。

说明:

Ø  一个预处理命令占用一个单独的行,命令末尾不使用分号作为结束符。

Ø  宏定义是专门用于预处理命令的一个专用名词,它与定义变量的含义不同,它只做字符替换,不分配内存空间。

2.不带参数的宏

1>用一个指定的标识符(即名字)来代替一个字符串,它的一般形式为

#define  标识符   字符串

Eg:

#define  MAX_NUM    100

它的作用是在本程序文件中使用指定的标识符MAX_NUM来替代  100这个字符串。

2>宏定义是用宏名代替一个字符串,也就是做简单的置换,不做正确性检查。(预编译时不做任何语法检查,只有在编译已被宏展开后的源程序时才会发现语法错误并报错)

3>宏定义不是C语句,不必在行末加分号。如果加了分号则会连分号一起进行替换

4>#definde出现在A处,则宏名的有效范围为定义命令之后到本源文件之后到本源文件结尾。

5>可以通过#undef命令终止宏定义的作用域.

#define MAX_NUM  100;

Void  main()

{

       …………………….               MAX_NUM的作用范围

       ………………….

};

#undedf  MAX_NUM

f()

{

  ………………………….

  …………………………

}

说明:当解除宏定义时,只需要指出宏标识符而不必给出后面的字符串。

6>在进行宏定义时,可以引用已定义的宏名,可以层层置换(即宏可以嵌套)

#define  PI  3.141596

#define  R   3.0

#define  L   2*PI*R

#define  S   PI*R*R

7>对程序中使用双引号括起来的字符串,即使与宏名相同,也不进行置换。

eg;

printf(“L =%f\n,s=%f\n”,L,S);

在printf中双引号内的L不进行替换,双引号外的进行替换。


  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值