#define 用法整理

  网络上资料里对 #define 的用法已经有很多的说明,在这里对现有的一些内容进行整理,希望能够对大家有帮助作用。

  一、define的简单用法

  1.简单的define定义

  #define MAXTIME 1000

  一个简单的MAXTIME就定义好了,它代表1000,如果在程序里面写

  if(i<MAXTIME){.........}

  编译器在处理这个代码之前会对MAXTIME进行处理替换为1000。

  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 Conn(x,y) x##y
  #define ToChar(x) #@x
  #define ToString(x) #x

  x##y表示什么?表示x连接y,举例说:
  int n = Conn(123,456);  结果就是  n=123456;
  char* str = Conn("asdf", "adf")  结果就是 str = "asdfadf";

  再来看#@x,其实就是给x加上单引号,结果返回是一个const char。举例说:
  char a = ToChar(1);结果就是a='1';
  做个越界试验char a = ToChar(123);结果是a='3';
  但是如果你的参数超过四个字符,编译器就给给你报错了!error C2015: too many characters in constant :P

  最后看看#x,估计你也明白了,他是给x加双引号
  char* str = ToString(123132);  结果就是 str="123132";

  3.define的多行定义

  define可以替代多行的代码,例如MFC中的宏定义

  #define MACRO(arg1, arg2) do { \
  /* declarations */ \
  stmt1; \
  stmt2; \
  /* ... */ \
  } while(0) /* (no trailing ; ) */


  关键是要在每一个换行的时候加上一个"\

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

  如下:


  #ifdef WINDOWS
  ......
  ......
  #endif
  #ifdef LINUX
  ......
  ......
  #endif

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

  5.如何定义宏、取消宏

  //定义宏
  #define [MacroName] [MacroValue]
  //取消宏
  #undef [MacroName]
  普通宏
  #define PI (3.1415926)

  带参数的宏
  #define max(a,b) ((a)>(b)? (a),(b))
  关键是十分容易产生错误,包括机器和人理解上的差异等等。

  6.条件编译
  #ifdef XXX…(#else) …#endif
  例如 #ifdef DV22_AUX_INPUT
  #define AUX_MODE 3
  #else
  #define AUY_MODE 3
  #endif
  #ifndef XXX … (#else) … #endif

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

  8.一些注意事项
    1) 不能重复定义.除非定义完全相同.#define A(x) … 和#define A 是重复定义.
    2) 可以只定义符号,不定义值.如#define AAA

  二、define和typedef的区别
  1) #define是预处理指令,在编译预处理时进行简单的替换,不作正确性检查,不关含义是否正确照样带入,只有在编译已被展开的源程序时才会发现可能的错误并报错。例如:
  #define PI 3.1415926
  程序中的:area=PI*r*r 会替换为3.1415926*r*r,如果你把#define语句中的数字9 写成字母g 预处理也照样带入。

  2)typedef是在编译时处理的。它在自己的作用域内给一个已经存在的类型一个别名,但是You cannot use the typedef specifier inside a function definition。

  3)typedef int * int_ptr;
  与
  #define int_ptr int *
  作用都是用int_ptr代表 int * ,但是二者不同,正如前面所说 ,#define在预处理 时进行简单的替换,而typedef不是简单替换 ,而是采用如同定义变量的方法那样来声明一种类型。也就是说;

  //refer to (xzgyb(老达摩))
  #define int_ptr int *
  int_ptr a, b; //相当于int * a, b; 只是简单的宏替换

  typedef int* int_ptr;
  int_ptr a, b; //a, b 都为指向int的指针,typedef为int* 引入了一个新的助记符

  这也说明了为什么下面观点成立
  //QunKangLi(维护成本与程序员的创造力的平方成正比)
  typedef int * pint ;
  #define PINT int *

  那么:
  const pint p ;//p不可更改,但p指向的内容可更改
  const PINT p ;//p可更改,但是p指向的内容不可更改。

  pint是一种指针类型 const pint p 就是把指针给锁住了 p不可更改,而const PINT p 是const int * p 锁的是指针p所指的对象。

  3)也许您已经注意到#define 不是语句 不要在行末加分号,否则 会连分号一块置换。

  三、#define和const的区别

  1)差别:

  const#define最大的差别在于:前者在堆栈分配了空间,而后者只是把具体数值直接传递到目标变量罢了。或者说,const的常量是一个Run-Time的概念,他在程序中确确实实的存在可以被调用、传递。而#define常量则是一个Compile-Time概念,它的生命周期止于编译期:在实际程序中他只是一个常数、一个命令中的参数,没有实际的存在。

  const常量存在于程序的数据段.

  #define常量存在于程序的代码段。

  2)优缺点:

  至于两者的优缺点,要看具体的情况了。一般的常数应用,我个人认为#define是一个更好的选择:

  i.run-time的角度来看,他在空间上和时间上都有很好优势。

  ii.compile-time的角度来看,类似m=t*10的代码不会被编译器优化,t*10的操作需要在run-time执行。而#define的常量会被合并。

  但是:如果你需要粗鲁的修改常数的值,那就的使用const了,因为后者在程序中没有实际的存在.

  另外在头文件中使用 #define 可以避免头文件重复包含的问题,这个功能,是const无法取代的。

  四、#define和inline的区别
  
1.宏是代码处不加任何验证的简单替代,而内联函数是将代码直接插入调用处,而减少了普通函数调用时的资源消耗。
  2.宏不是函数,只是在编译前预处理阶段将程序中有关字符串替换成宏体。
  3.inline是函数,但在编译中不单独产生代码,而是将有关代码嵌入到调用处。
  许多C程序员的经验表明,宏会为程序设计带来不小的安全隐患,许多由宏产生的问题就是实证。所以在C++中引入的const关键字以及inline函数可以完成与宏同样的功能,且更安全,更可靠。

参考链接列表:
http://www.cnblogs.com/minhost/archive/2009/01/07/1370806.html
http://www.cppblog.com/kerlw/archive/2007/04/20/22381.html
http://bbs.xml.org.cn/blog/more.asp?name=zhu_ruixian&id=23461
http://student.csdn.net/space.php?uid=100640&do=blog&id=26057

posted @ 2011-05-16 17:20  Gage-Xu  阅读(860)  评论(2编辑  收藏  举报