#define 用法

来源:互联网 发布:c语言prime什么意思 编辑:程序博客网 时间:2024/05/13 13:54

转自:http://blog.csdn.net/zhangliang_571/article/details/8518652

1.简单的define定义

#define MAXTIME 1000

2.define的“函数定义”

define可以像函数那样接受一些参数,如下

#define max(x,y) (x)>(y)?(x):(y);

因为这个“函数”没有类型检查,就好像一个函数模板似的,没有模板那么安全就是了。

但是这样做的话存在隐患,例子如下:
#define Add(a,b) a+b;如果遇到如:c * Add(a,b) * d的时候就会出现问题。

另外举一个例子:
#define pin (int*);
pin a,b;
本意是a和b都是int型指针,但是实际上变成int* a,b;
a是int型指针,而b是int型变量。
这时应该使用typedef来代替define,这样a和b就都是int型指针了。

我们在定义的时候,养成一个良好的习惯,建议所有的层次都要加括号。

3.宏的单行定义(少见用法)

#define A(x) T_##x
#define B(x) #@x
#define C(x) #x

我们假设:x=1,则有:

A(1)------〉T_1
B(1)------〉'1'
C(1)------〉"1"

4.define的多行定义

define可以替代多行的代码,例如MFC中的宏定义(非常的经典,虽然让人看了恶心)

#define MACRO(arg1, arg2) do { \
/* declarations */ \
stmt1; \
stmt2; \
/* ... */ \
} while(0) /* (no trailing ; ) */
关键是要在每一个换行的时候加上一个"\"

5.在大规模的开发过程中,特别是跨平台和系统的软件里,define最重要的功能是条件编译。

就是:
#ifdef WINDOWS
......
......
#endif
#ifdef LINUX
......
......
#endif

可以在编译的时候通过#define设置编译环境。

6.如何定义宏、取消宏

#define [MacroName] [MacroValue]  //定义宏
#undef [MacroName] //取消宏
#define PI (3.1415926) //普通宏
#define max(a,b) ((a)>(b)? (a),(b)) //带参数的宏
7.条件编译
#ifdef XXX…(#else) … #endif
例如
#ifdef DV22_AUX_INPUT
#define AUX_MODE 3 
#else
#define AUY_MODE 3
#endif
#ifndef XXX … (#else) … #endif

8. 防止一个头文件被重复包含
由于头文件包含可以嵌套,那么C文件就有可能多次包含同一个头文件,就可能出现重复定义的问题的。
通过条件编译开关来避免重复包含(重复定义)
例如
#ifndef __headerfileXXX__
#define __headerfileXXX__

//文件内容

#endif

 

Instances:

1.防止一个头文件被重复包含

#ifndef COMDEF_H

#define COMDEF_H

 //头文件内容

#endif

当你所建的工程有多个源文件组成时,很可能会在多个文件里头包含了同一个头文件,如果借用上面的宏定义就能够避免同一个头文件被重复包含时进行多次编译。因为当它编译第一个头文件时总是没有定义#defineCOMDEF_H,那么它将编译一遍头文件中所有的内容,包括定义#define COMDEF_H。这样编译再往下进行时如果遇到同样要编译的头文件,那么由于语句#ifndefCOMDEF_H的存在它将不再重复的编译这个头文件。

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

typedef  unsignedchar      boolean;     /*Boolean value type. */

typedef  unsigned longint  uint32;      /* Unsigned 32 bitvalue */

typedef  unsigned short    uint16;      /* Unsigned 16 bit value */

typedef  unsignedchar      uint8;      /* Unsigned 8  bit value */

typedef  signed longint    int32;       /* Signed32 bit value */

typedef  signedshort      int16;       /* Signed 16 bit value */

typedef  signedchar        int8;        /*Signed 8  bit value */

//下面的不建议使用

typedef  unsigned char    byte;         /* Unsigned8  bit value type. */

typedef  unsignedshort    word;        /* Unsinged 16 bit value type. */

typedef  unsigned long    dword;        /* Unsigned 32 bit valuetype. */

typedef  unsigned char    uint1;        /* Unsigned8  bit value type. */

typedef  unsignedshort    uint2;        /*Unsigned 16 bit value type. */

typedef  unsigned long    uint4;        /* Unsigned 32 bit valuetype. */

typedef  signedchar      int1;         /* Signed8  bit value type. */

typedef  signedshort      int2;        /* Signed 16 bit value type. */

typedef  longint          int4;        /* Signed 32 bit value type. */

typedef  signedlong      sint31;       /* Signed 32 bit value */

typedef  signedshort      sint15;      /* Signed 16 bit value */

typedef  signedchar      sint7;        /* Signed8  bit value */

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

#define  MEM_B( x )  ( *((byte *) (x) ) )

#define  MEM_W( x )  ( *((word *) (x) ) )

4.求最大值和最小值

 #define  MAX( x, y ) ( ((x) > (y)) ?(x) : (y) )

 #define  MIN( x, y ) ( ((x) < (y)) ?(x) : (y) )

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

#define FPOS( type, field )  &(( type *) 0)-> field )

6.得到一个结构体中field所占用的字节数

#define FSIZ( type, field ) sizeof( ((type *)0)->field )

7.按照LSB格式把两个字节转化为一个Word

#define  FLIPW( ray ) ( (((word)(ray)[0]) * 256) + (ray)[1] )

8.按照LSB格式把一个Word转化为两个字节

#define  FLOPW( ray, val ) \

                   (ray)[0]= ((val) / 256); \

                   (ray)[1]= ((val) & 0xFF)

9.得到一个变量的地址(word宽度)

#define  B_PTR( var )  ((byte *) (void *) &(var) )

#define  W_PTR( var )  ((word *) (void *) &(var) )

10.得到一个字的高位和低位字节

#define  WORD_LO(xxx)  ((byte)((word)(xxx) & 255))

#define  WORD_HI(xxx)  ((byte)((word)(xxx) >> 8))

11.返回一个比X大的最接近的8的倍数

#define RND8( x)       ((((x) + 7) / 8 ) * 8 )

12.将一个字母转换为大写

#define  UPCASE( c ) ( ((c) >= 'a'&& (c) <= 'z') ? ((c) - 0x20) : (c) )

13.判断字符是不是10进值的数字

#define  DECCHK( c ) ((c) >= '0' &&(c) <= '9')

14.判断字符是不是16进值的数字

#define  HEXCHK( c ) ( ((c) >= '0'&& (c) <= '9') ||\

                  ((c) >= 'A' && (c) <= 'F') ||\

((c) >= 'a'&& (c) <= 'f') )

15.防止溢出的一个方法

#define  INC_SAT( val )  (val= ((val)+1 > (val)) ? (val)+1 : (val))

16.返回数组元素的个数

#define  ARR_SIZE(a )  ( sizeof( (a) ) / sizeof( (a[0]) ) )

17.返回一个无符号数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) )

18.对于IO空间映射在存储空间的结构,输入输出处理

  #defineinp(port)         (*((volatile byte *)(port)))

  #defineinpw(port)        (*((volatile word *)(port)))

  #defineinpdw(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)))

19.使用一些宏跟踪调试

ANSI标准说明了五个预定义的宏名。它们是:

__LINE__

__FILE__

__DATE__

__TIME__

__STDC__

C++中还定义了 __cplusplus

如果编译器不是标准的,则可能仅支持以上宏名中的几个,或根本不支持。记住编译程序也许还提供其它预定义的宏名。

__LINE__ 及 __FILE__ 宏指示,#line指令可以改变它的值,简单的讲,编译时,它们包含程序的当前行数和文件名。

__DATE__ 宏指令含有形式为月/日/年的串,表示源文件被翻译到代码时的日期。

__TIME__ 宏指令包含程序编译的时间。时间用字符串表示,其形式为:分:秒

__STDC__ 宏指令的意义是编译时定义的。一般来讲,如果__STDC__已经定义,编译器将仅接受不包含任何非标准扩展的标准C/C++代码。如果实现是标准的,则宏__STDC__含有十进制常量1。如果它含有任何其它数,则实现是非标准的。

__cplusplus 与标准c++一致的编译器把它定义为一个包含至少6为的数值。与标准c++不一致的编译器将使用具有5位或更少的数值。

可以定义宏,例如:

当定义了_DEBUG,输出数据信息和所在文件所在行

#ifdef _DEBUG

#define DEBUGMSG(msg,date) printf(msg);printf(“%d%d%d”,date,_LINE_,_FILE_)

#else

#define DEBUGMSG(msg,date)

#endif

 20.宏定义防止错误使用小括号包含。

例如:

有问题的定义:#define DUMP_WRITE(addr,nr) {memcpy(bufp,addr,nr);bufp += nr;}

应该使用的定义: #difne DO(a,b) do{a+b;a++;}while(0)

例如:

if(addr)

    DUMP_WRITE(addr,nr);

else

    do_somethong_else();

宏展开以后变成这样:

if(addr)

    {memcpy(bufp,addr,nr); bufp += nr;};

else

    do_something_else();

gcc在碰到else前面的“;”时就认为if语句已经结束,因而后面的else不在if语句中。而采用do{} while(0)的定义,在任何情况下都没有问题。而改为 #defineDO(a,b) do{a+b;a++;}while(0) 的定义则在任何情况下都不会出错

21. define中的特殊标识符

#define Conn(x,y) x##y
#define ToChar(x) #@x
#define ToString(x) #x


int a=Conn(12,34);
char b=ToChar(a);
char c[]=ToString(a);
结果是 a=1234,b='a',c=”a”;

可以看出 ## 是简单的连接符,

#@用来给参数加单引号转换成单字符(最后一个字符)

#用来给参数加双引号即转成字符串

typedef和#define的用法与区别

一、typedef的用法

在C/C++语言中,typedef常用来定义一个标识符及关键字的别名,它是语言编译过程的一部分,但它并不实际分配内存空间,实例像:

typedef    int        INT;
typedef     int       ARRAY[10];
typedef    (int*)     pINT;

typedef可以增强程序的可读性,以及标识符的灵活性,但它也有“非直观性”等缺点。

二、#define的用法

#define为一宏定义语句,通常用它来定义常量(包括无参量与带参量),以及用来实现那些“表面似和善、背后一长串”的宏,它本身并不在编译过程中进行,而是在这之前(预处理过程)就已经完成了,但也因此难以发现潜在的错误及其它代码维护问题,它的实例像:

#define   INT             int
#define   TRUE          1
#define    Add(a,b)      ((a)+(b));
#define    Loop_10     for (int i=0;i<10; i++)

在Scott Meyer的Effective C++一书的条款1中有关于#define语句弊端的分析,以及好的替代方法,大家可参看。

三、typedef与#define的区别

从以上的概念便也能基本清楚,typedef只是为了增加可读性而为标识符另起的新名称(仅仅只是个别名),而#define原本在C中是为了定义常量,到了C++,const、enum、inline的出现使它也渐渐成为了起别名的工具。有时很容易搞不清楚与typedef两者到底该用哪个好,如#define INTint这样的语句,用typedef一样可以完成,用哪个好呢?我主张用typedef,因为在早期的许多C编译器中这条语句是非法的,只是现今的编译器又做了扩充。为了尽可能地兼容,一般都遵循#define定义“可读”的常量以及一些宏语句的任务,而typedef则常用来定义关键字、冗长的类型的别名。

宏定义只是简单的字符串代换(原地扩展),而typedef则不是原地扩展,它的新名字具有一定的封装性,以致于新命名的标识符具有更易定义变量的功能。请看上面第一大点代码的第三行:

typedef    (int*)       pINT;
以及下面这行:
#define     pINT2     int*

效果相同?实则不同!实践中见差别:pINT a,b;的效果同int *a; int*b;表示定义了两个整型指针变量。而pINT2 a,b;的效果同int *a, b;

表示定义了一个整型指针变量a和整型变量b。

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 小宝机器人一直停在联网界面怎么办 手机版的有道云笔记忘记邮箱怎么办 钡灌肠复查钡剂排空不良怎么办 两个月宝宝灌肠后不排便怎么办 一岁宝宝肠套叠灌肠后拉肚子怎么办 苹果手机自带的天气没有了怎么办? 衣服在洗衣机里忘记拿出来怎么办 苹果se手机系统占内存太大怎么办 客人把饭店老板打了民警怎么办 商场嫌品牌低端不让入驻怎么办 带着孩子坐飞机座位不在一起怎么办 公司老板跑路了员工该怎么办 超市买的衣服防盗扣忘记取了怎么办 在超市买的衣服那个扣没取怎么办啊 超市散称商品条码老记不住怎么办 app账号密码忘记了怎么办注销难 幼儿老师遇到家长比较孩子该怎么办 发的微信公众号内容重复了怎么办 招嫖诈骗微信转账被骗怎么办 朋友在深圳龙岗被传销骗了要怎么办 怀疑家里人被传销组织骗去了怎么办 怀疑家人被骗进传销了该怎么办 b本扣3分了怎么办2018 抖音里面就剩人头的视频怎么办 自学参加普通高考那小高考怎么办 如果小学生长胸只长了一个该怎么办 脸上毛多导致的毛孔粗怎么办 吃了激素药头发掉的厉害怎么办 剪发的剪子中间的螺丝扣总掉怎么办 染完头发后一段时间长新头发怎么办 睡觉头发老被老公压着怎么办 漆盖关节不自在怎么办?吃什么好 摆床头的位置后面是弧形位怎么办 君子兰的根全烂掉了只剩茎怎么办 老板不发工资怎么办 没签合同的 牙套粘在牙齿上的松了怎么办 缝的线长在肉里怎么办 小孩喜欢用舌头顶牙齿缝怎么办 1岁多小宝贝全身长红点怎么办 生完胸好涨但很难把奶吸出来怎么办 怀孕快9个月内裤上有白带怎么办