关于define,ifdef,ifndef和undefine

一、为什么要用宏

一般情况下,源程序中所有的行都参加编译。但是有时希望对其中一部分内容只在满足一定条件才进行编译,也就是对一部分内容指定编译的条件,这就是“条件编译”。有时,希望当满足某条件时对一组语句进行编译,而当条件不满足时则编译另一组语句。


在头文件中使用#ifdef和#ifndef是非常重要的,可以防止双重定义的错误。比如,在b.h中会include   "a.h"  ,在"c.h"中会include   "b.h"及include"a.h", 这时,如果不用ifndef/endif,就会包含两次a.h,产生错误。

如你在头文件aaa.h中定义了一个类aaa如下:   

  class   aaa   
  {   
  };   
  如果两次#include   "aaa.h"(不见得是直接,也有可能两个不同的头文件中都包含了这个头文件)就会出错,因为相同的类不能定义两次。把aaa.h稍做修改:   
  #ifndef   _aaa_   
  #define   _aaa_   
  class   aaa   
  {   
  };   
  #endif   
  就可以避免这样的问题。因为当你已经包含过这个文件,_aaa_就会有了定义,那么#ifndef的条件为假,就不会再执行后面的类定义了。  


二、一些技巧

1、

命名

<标识>在理论上来说可以是自由命名的,但每个头文件的这个“标识”都应该是唯一的。标识的命名规则一般是头文件名全大写,前后加下划线,并把文件名中的“.”也变成下划线,如:stdio.h

#ifndef _STDIO_H_ 
#define _STDIO_H_

......

#endif

2、调试时使用条件编译

满足条件就编译,否则就不编译,如果有一段代码有时候你想要,有时候又不想编译(比如为了调试),可以这样写:   

  #if   1(0)   
          xxxxxx   
          xxxxxx   
  #endif   
  需要的时候写1,不要的时候改为0就可以了


3、在#ifndef中定义变量出现的问题(一般不定义在#ifndef中)。

#ifndef AAA
#define AAA
...
int i;
...
#endif
里面有一个变量定义
在vc中链接时就出现了i重复定义的错误,而在c中成功编译。

结论:

(1).当你第一个使用这个头的.cpp文件生成.obj的时候,int i 在里面定义了当另外一个使用这个的.cpp再次[单独]生成.obj的时候,int i 又被定义然后两个obj被另外一个.cpp也include 这个头的,连接在一起,就会出现重复定义.

(2).把源程序文件扩展名改成.c后,VC按照C语言的语法对源程序进行编译,而不是C++。在C语言中,若是遇到多个int i,则自动认为其中一个是定义,其他的是声明。

(3).C语言和C++语言连接结果不同,可能(猜测)时在进行编译的时候,C++语言将全局
变量默认为强符号,所以连接出错。C语言则依照是否初始化进行强弱的判断的。(参考)

解决方法:

(1).把源程序文件扩展名改成.c。

(2).推荐解决方案:
.h中只声明 extern int i;在.cpp中定义

<x.h>
#ifndef __X_H__
#define __X_H__
extern int i;
#endif //__X_H__
<x.c>
int i;

总结:变量一般不要定义在.h文件中


 4、撤销条件编译

#undef只是撤消掉掉原来定义的宏,
但是不会取消掉你已经用这个宏定义的变量
#define   X   extern
x   int   a;
#undef   X

你仍然可以使用这个a,但不能用X了,当然你再定义X成什么就随便了
你也可以再定义成
#define   X   extern
x   int   a;
#undef   X
#define   X   int
X   b;
#undef   X 



参考:


http://blog.csdn.net/bigpretty/article/details/5018261

在C/C++编程语言中,`#ifdef`, `#ifndef`和`#define`都是预处理器指令,它们在代码编译前对程序进行条件性的控制处理。以下是这三个指令的详细介绍及用途: ### 1. `#define` `#define` 用于定义一个宏 (macro)。它将一段文本替换到其位置,直到遇到下一个 `#undef` 或重新定义同名的宏。宏通常用于简化大量的代码重用或提供特定的名称替代。例如,定义一个宏用于表示某种类型的长度单位: ```c++ #define LENGTH_UNIT "cm" ``` 之后在代码中可以像引用普通变量一样使用这个宏: ```c++ double length = 5 * LENGTH_UNIT; ``` 这里的代码实际上会被编译器解释为 `double length = 5 * "cm";`。 ### 2. `#ifdef` `#ifdef` 用于条件编译。它的基本作用是在代码中选择性地包括某些部分,根据宏的定义情况来进行判断。如果指定的宏已经被定义了 (`#defined`),则包含相应的代码块;如果没有定义,则跳过这部分代码。这对于跨平台编译非常有用,比如针对不同的操作系统或硬件特性进行代码优化或配置调整: ```c++ #if defined(_WIN32) // Windows 特定代码 #else // 其他操作系统代码 #endif ``` ### 3. `#ifndef` `#ifndef` 相似于 `#ifdef`,但它用于判断宏是否尚未被定义的情况。当宏未定义(`#ifndef`)时,才包括相应的代码块;当宏已被定义(`#ifdef`)时,则跳过这部分代码。 组合使用 `#ifdef` 和 `#ifndef` 通常是为了确保某个宏要么完全定义,要么完全未定义,避免在宏被同时定义和未定义的情况下导致的意外结果。 这些指令的合理运用可以使代码更具灵活性和适应性,特别是在需要根据不同环境或配置生成不同版本的代码时显得尤为重要。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值