浅谈#ifdef等宏定义在软件开发中的妙用

本文详细介绍了C语言中预处理指令的使用方法,包括如何使用#ifdef、#ifndef、#if等指令进行条件编译,以实现代码的功能开关、硬件适配及版本控制等功能。

使用以下几种方法,假设我们已在程序首部定义#ifdef DEBUG与#ifdef TEST:

1.利用#ifdef/#endif将某程序功能模块包括进去,以向某用户提供该功能。

  在程序首部定义#ifdef HNLD:

  #ifdef HNLD

  #include"n166_hn.c"

  #endif

  如果不许向别的用户提供该功能,则在编译之前将首部的HNLD加一下划线即可。

  2.在每一个子程序前加上标记,以便追踪程序的运行。

  #ifdef DEBUG

  printf(" Now is in hunan !");

  #endif

  3.避开硬件的限制。有时一些具体应用环境的硬件不一样,但限于条件,本地缺乏这种设备,于是绕过硬件,直接写出预期结果。具体做法是:

  #ifndef TEST

  i=dial();

  //程序调试运行时绕过此语句

  #else

  i=0;

  #endif

  调试通过后,再屏蔽TEST的定义并重新编译,即可发给用户使用了。

―――――――――――――――――――――――――――――――――――――――

#define TARGET_LITTLE_ENDINA1

#define TARGET_BIG_ENDINA0

#ifdef TARGET_LITTLE_ENDINA

call little endina function

#else

call big endina function

#endif

上 面的今天写的代码,发现我不管把TARGET_LITTLE_ENDINA和TARGET_BIG_ENDINA定义成0或者1,调用的都是little endina函数,一直找不到问题所在,看看代码也没有什么问题。经过分析和查找相关的文档,原来是自己没有理解#if和#ifdef之间的区别。

对于#if需要是一个表达式,如果表达式为1则调用#if下面的代码。

对于#ifdef需要的只是这个值有没有定义,并不关心这个值是什么。

表明之间的区别问题就变得非常的容易,只要把上述代码中的#ifdef改成#if就可以达到目的。

从 这个问题发现自己在一些基本的C或C++的语法上面还是有很大的不足,到网上查找一些书籍,对这方面介绍的也不是特别多,相比而言,MSDN还是比较全 面。平时比较痛恨MS的,不过平心而论,MS对于开发软件工具和文档做的还是相当不错,尤其是开发文档方面非常全面,自己在项目SDK的开发过程中也需要 加强这方面的工作。

―――――――――――――――――――――――――――――――――

最近在用C语写一些程序,发现#ifdef,#else,#endif和#ifndef,#else,#endif在UCOS-II中有大量的应用,于是到网上查了一些相关的解释.

#ifdef的用法

灵活使用#ifdef指示符,我们可以区隔一些与特定头文件、程序库和其他文件版本有关的代码。

代码举例:新建define.cpp文件

#include "iostream.h"

int main()

{

#ifdef DEBUG

cout<< "Beginning execution of main()";

#endif

return 0;

}

运行结果为:Press any key to continue

改写代码如下:

#include "iostream.h"

#define DEBUG

int main()

{

#ifdef DEBUG

cout<< "Beginning execution of main()";

#endif

return 0;

}

运行结果为:Beginning execution of main()

Press any key to continue

更一般的情况是,#define语句是包含在一个特定的头文件中。

比如,新建头文件head.h,在文件中加入代码:

#ifndef DEBUG

#define DEBUG

#endif

而在define.cpp源文件中,代码修改如下:

#include "iostream.h"

#include "head.h"

int main(){

#ifdef DEBUG

cout<< "Beginning execution of main()";

#endif

return 0;

}

运行结果如下:Beginning execution of main()

Press any key to continue

结论:通过使用#ifdef指示符,我们可以区隔一些与特定头文件、程序库和其他文件版本有关的代码。

―――――――――――――――――――――――――――――――――――――――

常常在建立header file的时候需要先写一段文字

比如下面这段话

#ifdef HEADERFILENAME_H

#define HEADERFILENAME_H

class ClassName

{

...

};

#endif

那段#ifdef有必要写吗?

其实有些无写都不会影响代码的Runtime

不过对运行速度和文件大小有一定的影响

大概很多人很喜欢用#i nclude来抓取文件吧

炎也很喜欢

总是在main.cpp中include一次

然后又在classfile.cpp中又使用一次

每次都include同样的Headerfile.h

这样就导致了Compiler运作的时候在link的时候会重复同样的headerfile内容

相同重复的内容出现就有可能导致不良的情况的发生

即时没有compilerError或者RunrimeError

也会让程序运行缓慢,想想看吧,在重复compiler一段Code之后产生的程序大小

―――――――――――――――――――――――――――――――――――――――

预处理就是在进行编译的第一遍词法扫描和语法分析之前所作的工作。说白了,就是对源文件进行编译前,先对预处理部分进行处理,然后对处理后的代码进行编译。这样做的好处是,经过处理后的代码,将会变的很精短。

关于预处理命令中的文件包含(#i nclude),宏定义(#define),书上已经有了详细的说明,在这里就不详述了。这里主要是对条件编译(#ifdef,#else,#endif,#if等)进行说明。以下分3种情况:

1:情况1:

#ifdef _XXXX

...程序段1...

#else

...程序段2...

#endif

这表明如果标识符_XXXX已被#define命令定义过则对程序段1进行编译;否则对程序段2进行编译。

例:

#define NUM

.............

.............

.............

#ifdef NUM

printf("之前NUM有过定义啦!:) \n");

#else

printf("之前NUM没有过定义!:( \n");

#endif

}

如果程序开头有#define NUM这行,即NUM有定义,碰到下面#ifdef NUM的时候,当然执行第一个printf。否则第二个printf将被执行。

我认为,用这种,可以很方便的开启/关闭整个程序的某项特定功能。

2:情况2:

#ifndef _XXXX

...程序段1...

#else

...程序段2...

#endif

这里使用了#ifndef,表示的是if not def。当然是和#ifdef相反的状况(如果没有定义了标识符_XXXX,那么执行程序段1,否则执行程序段2)。例子就不举了。

3:情况3:

#if 常量

...程序段1...

#else

...程序段2...

#endif

这里表示,如果常量为真(非0,随便什么数字,只要不是0),就执行程序段1,否则执行程序段2。

我认为,这种方法可以将测试代码加进来。当需要开启测试的时候,只要将常量变1就好了。而不要测试的时候,只要将常量变0。

# ifdef #ifndef 等用法

文件中的#ifndef

头件的中的#ifndef,这是一个很关键的东西。比如你有两个C文件,这两个C文件都include了同一个头文件。而编译时,这两个C文件要一同编译成一个可运行文件,于是问题来了,大量的声明冲突。

还是把头文件的内容都放在#ifndef和#endif中吧。不管你的头文件会不会被多个文件引用,你都要加上这个。一般格式是这样的:

#ifndef <标识>

#define <标识>

......

......

#endif

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

#ifndef _STDIO_H_

#define _STDIO_H_

......

#endif

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

#ifndef AAA

#define AAA

...

int i;

...

#endif

里面有一个变量定义

在vc中链接时就出现了i重复定义的错误,而在c中成功编译。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值