转自:https://blog.csdn.net/zhangchiytu/article/details/7563329

先看个例子:
#define TARGET_LITTLE_ENDINA 1
#define TARGET_BIG_ENDINA   0

#ifdef TARGET_LITTLE_ENDINA
call little endina function
#else
call big endina function
#endif
不管把 TARGET_LITTLE_ENDINA 和 TARGET_BIG_ENDINA定义成0或者1,甚至后面不写这个0或者1 ,调用的都是little endina函数,这段代码是有问题的,就是没有理解#if和#ifdef之间的区别。

#if 的使用说明
#if的后面接的是表达式,如果表达式为1,则编译#if下面的代码

 #if (MAX==10)||(MAX==20)
...code...
#endif

它的作用是:如果(MAX==10)||(MAX==20)成立,那么编译器就会把其中的#if 与 #endif之间的代码编译进去(注意:是编译进去,不是执行!!)

#ifdef 的说明
#ifdef 后面接的是一个宏

 #ifdef (x)
...code...
#endif

这个#ifdef 它不管里面的“x”的逻辑是“真”还是“假”,它只管这个程序前面的宏定义里面有没有定义“x”这个宏(即在这里#define  x 1和#define  x 0等效,都等同于#define x)。

如果定义了x这个宏,那么编译器会编译中间的…code…否则直接忽视中间的…code…代码。

#if defined的使用
#if defined() 的使用和#ifdef的用法一致
#if !defined()又和 #ifndef 的用法一致。

最后强调两点:
第一:这几个宏定义只是决定代码块是否被编译!
第二:别忘了#endif

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

 #include "iostream.h"
int main()
{
  #ifdef DEBUG
cout<< "Beginning execution of main()";
  #endif
return ;
}

运行结果:Press any key to continue

改写代码如下:

 #include "iostream.h"
#define DEBUG
int main()
{
#ifdef DEBUG
cout<< "Beginning execution of main()";
#endif
return ;
}

运行结果为: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 ;
}

运行结果如下:Beginning execution of main()
Press any key to continue 
结论:通过使用#ifdef指示符,我们可以区隔一些与特定头文件、程序库和其他文件版本有关的代码。

================================================================================

为各个版本的软件升级工作是很困难的,因为这些补丁程序都是在一套软件的基础上不断地修改与扩充而编写的,并由不同的标志文件转入到不同的模块,虽然程序 体积在不断扩大,但丝毫不影响老用户的功能,这主要是得益于C程序的#ifdef/#else/#endif的作用。

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

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

  在程序首部定义#ifdef HNLD:

 #define 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=;
#endif

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

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

#if 和#ifdef的区别的更多相关文章

  1. #if和#ifdef的区别

    学习STM32偶然发现:在Keil中直接预先定义宏USE_STDPERIPH_DRIVER,但是却没有指定宏的值.而在头文件中判断用的是如下代码: #ifdef USE_STDPERIPH_DRIVE ...

  2. C 和 Object-C中的 #ifdef #ifndef

    很多宏是为了进行条件编译.一般情况下,源程序中所有的行都参加编译.但是有时希望对其中一部分内容只在满足一定条件才进行编译,也就是对一部分内容指定编译的条件,这就是“条件编译”.有时,希望当满足某条件时 ...

  3. darknet是如何对数据集做resize的?

    在准备数据集时,darknet并不要求我们预先对图片resize到固定的size. darknet自动帮我们做了图像的resize. darknet训练前处理 本文所指的darknet版本:https ...

  4. #ifdef 和 #if defined 的区别 -- 转

    #ifdef 和 #if defined 的区别在于,后者可以组成复杂的预编译条件,比如 #if defined (AAA) && defined (BBB) xxxxxxxxx #e ...

  5. #if 与 #ifdef 之间的区别

    先来看个例子: #define TARGET_LITTLE_ENDINA 1 #define TARGET_BIG_ENDINA 0 #ifdef TARGET_LITTLE_ENDINA call ...

  6. #ifdef 和 #if defined的区别

    #ifdef 和 #if defined的区别在于,后者可以组成复杂的预编译条件,比如 #if defined (AAA) && defined (BBB)xxxxxxxxx#endi ...

  7. #if、#ifdef、#if defined之间的区别【转】

    转自:http://quanminchaoren.iteye.com/blog/1870977 #if的使用说明 #if的后面接的是表达式 #if (MAX==10)||(MAX==20) code. ...

  8. C开发之----#if、#ifdef、#if defined之间的区别

    #if的使用说明 #if的后面接的是表达式 #if (MAX==10)||(MAX==20) code... #endif 它的作用是:如果(MAX==10)||(MAX==20)成立,那么编译器就会 ...

  9. #if和#ifdef区别

    #if  是要去判断, 跟值有关 #ifdef  只要定义了即可, 就会走下面的代码, 不管值是0还是1 所以一般都是用#ifdef DEBUG调试

随机推荐

  1. 详细解析 HBASE 配置的各种要点

    文章更新于:2020-04-06 安装惯例,需要的文件附上链接放在文首. 文件名:hbase-2.2.4-bin.tar.gz 文件大小:213.24 MB 下载链接:http://download. ...

  2. php-fpm cgi fast-cgi

    基础 在整个网站架构中,Web Server(如Apache)只是内容的分发者.举个栗子,如果客户端请求的是 index.html,那么Web Server会去文件系统中找到这个文件,发送给浏览器,这 ...

  3. git rebase解决合并冲突

    git rebase解决合并冲突   记录合并冲突解决方法,使用的git rebase,感觉很好用 1.git rebase 文档 https://git-scm.com/docs/git-rebas ...

  4. group_concat有长度限制

    group_concat有长度限制     group_concat 详细用法请点此链接.   group_concat有长度限制!长度陷阱用了group_concat后,select里如果使用了li ...

  5. Python 操作mysql数据库之 SQLAlchemy 案例详解

      前言: 字段声明类型中,最右边的是数据库中对应的字段,我们依然可以使用,其左边的的 SQLAchemy 则是其自身封装的自定义类型. 本篇不会讲太多的理论知识,因为这个实用性更强,所以通篇全部都是 ...

  6. Mysqldump参数大全 这 些参数 不同于 mysql 的那些参数(下边文章开头有链接) :2 种类型的参数含义是不一样的

    Mysqldump参数大全  这 些参数 不同于 mysql 的那些参数  :2 种类型的参数含义是不一样的 Mysqldump参数大全(参数来源于mysql5.5.19源码) 参数 参数说明 --a ...

  7. 算法竞赛 从c到c++3

    const 常指针,指向固定位置,不能再次修改指向的位置,需要初始化,const 加在“*”号后面,名称前面,例如 int *const p: 指向常量的指针,不能修改指向地址的内容,相当于常引用,c ...

  8. Android Them+SharedPreferences 修改程序所有view字体颜色、大小和页面背景

    有这么一个需求,可以对页面的样式进行选择,然后根据选择改变程序所有字体颜色和页面背景.同时下一次启动程序,当前设置依然有效. 根据需求,我们需要一种快速,方便,有效的方式来实现需求,然后可以通过And ...

  9. JUC并发编程基石AQS源码之结构篇

    前言 AQS(AbstractQueuedSynchronizer)算是JUC包中最重要的一个类了,如果你想了解JUC提供的并发编程工具类的代码逻辑,这个类绝对是你绕不过的.我相信如果你是第一次看AQ ...

  10. FormCloseQuery

    FormCloseQuery是一个事件回调函数,Close是一个功能函数.而FormCloseQuery与窗口的close有什么不同,通过跟踪Call stack发生在调用Close()函数关闭窗口时 ...