#define 以及与typedef 、 inline的区别
什么是define
宏定义,简单的理解就是替换,其实这也是本质。如果熟悉g++编译过程的话,会了解到一个概念叫做预处理,就是在编译之前做个处理。这个过程并不像编译那么复杂,就是简单的递归替换和删除。替换的就是宏定义和include文件,删除注释。注意这里我们谈到一个概念,递归替换,这个其实是很常见的,比如你的程序中include一个.h文件,但是这个.h文件中还引入了另一个.h文件,那么这个时候就需要进行递归替换。
1.简单的define定义
#define MAXTIME 1000
一个简单的MAXTIME就定义好了,它代表1000,如果在程序里面写
if(i<MAXTIME){.........}
编译器在处理这个代码之前会对MAXTIME进行处理替换为1000。
这样的定义看起来类似于普通的常量定义CONST,但也有着不同,因为define的定义更像是简单的文本替换,而不是作为一个量来使用,这个问题在下面反映的尤为突出。
2.define的“函数定义”
define可以像函数那样接受一些参数,如下
#define max(x,y) (x)>(y)?(x):(y);
这个定义就将返回两个数中较大的那个,看到了吗?因为这个“函数”没有类型检查,就好像一个函数模板似的,当然,它绝对没有模板那么安全就是了。可以作为一个简单的模板来使用而已。
但是这样做的话存在隐患,例子如下:
#define Add(a,b) a+b;
在一般使用的时候是没有问题的,但是如果遇到如:c * Add(a,b) * d的时候就会出现问题,代数式的本意是a+b然后去和c,d相乘,但是因为使用了define(它只是一个简单的替换),所以式子实际上变成了
c*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.头文件(.h)可以被头文件或C文件包含
重复包含(重复定义)
由于头文件包含可以嵌套,那么C文件就有可能包含多次同一个头文件,就可能出现重复定义的问题的。
通过条件编译开关来避免重复包含(重复定义)
例如
#ifndef __headerfileXXX__ #define __headerfileXXX__ … //文件内容 … #endif
下面我们将c++ 常用的宏定义罗列一下:
#空指令,无任何效果 #include //包含一个源代码文件 #define //定义宏 #undef //取消已定义的宏 #if //如果给定条件为真,则编译下面代码 #ifdef //如果宏已经定义,则编译下面代码 #ifndef //如果宏没有定义,则编译下面代码 #elif //如果前面的#if给定条件不为真,当前条件为真,则编译下面代码 #endif //结束一个#if……#else条件编译块 #error //停止编译并显示错误信息
#define和别名typedef的区别
1) 执行时间不同,typedef在编译阶段有效,typedef有类型检查的功能;#define是宏定义,发生在预处理阶段,不进行类型检查;
2) 功能差异,typedef 用来定义类型的别名,定义与平台无关的数据类型,与 struct的结合使用等。#define不只是可以为类型取别名,还可以定义常量、变量、编译开关等。
3) 作用域不同,#define没有作用域的限制,只要是之前预定义过的宏,在以后的程序中都可以使用。而typedef有自己的作用域。
#define与inline的区别
1) #define是关键字,inline是函数;
2) 宏定义在预处理阶段进行文本替换,inline函数在编译阶段进行替换;
3) inline函数有类型检查,相比宏定义比较安全;