转自: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下面的代码

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

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

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

  1. #ifdef (x)
  2. ...code...
  3. #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文件:

  1. include "iostream.h"
  2. int main()
  3. {
  4.   #ifdef DEBUG
  5. cout<< "Beginning execution of main()";
  6.   #endif
  7. return ;
  8. }

运行结果:Press any key to continue

改写代码如下:

  1. include "iostream.h"
  2. #define DEBUG
  3. int main()
  4. {
  5. #ifdef DEBUG
  6. cout<< "Beginning execution of main()";
  7. #endif
  8. return ;
  9. }

运行结果为:Beginning execution of main()
Press any key to continue

更一般的情况是,#define语句是包含在一个特定的头文件中。
比如,新建头文件head.h,在文件中加入代码:

  1. #ifndef DEBUG
  2. #define DEBUG
  3. #endif

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

  1. include "iostream.h"
  2. include "head.h"
  3. int main()
  4. {
  5. #ifdef DEBUG
  6. cout<< "Beginning execution of main()";
  7. #endif
  8. return ;
  9. }

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

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

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

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

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

  在程序首部定义#ifdef HNLD:

  1. #define HNLD
  2.  
  3. #ifdef HNLD
  4. #include"n166_hn.c"
  5. #endif

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

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

  1. ifdef DEBUG
  2.   printf(" Now is in hunan !");
  3. endif

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

  1. ifndef TEST
  2.   i=dial();  //程序调试运行时绕过此语句
  3. else
  4.   i=;
  5. 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. 【翻译】OpenVINO Pre-Trained 预训练模型介绍

    OpenVINO 系列软件包预训练模型介绍 本文翻译自 Intel OpenVINO 的  "Overview of OpenVINO Toolkit Pre-Trained Models& ...

  2. Android AndroidManifest.xml详解

    AndroidManifest.xml简述: AndroidManifest.xml 是每个android程序中必须的文件.它位于整个项目的根目录,描述了package中暴露的组件(activitie ...

  3. css3新的选择器

    CSS3新的选择器 ele[att^="val"] /*属性att的值以val开头的元素*/ ele[att$="val"] /*属性att的值以val结尾的元 ...

  4. C语言输出菱形

    #include<stdio.h> #include<string.h> int main(){          int data[7][7] = {0};     for( ...

  5. VM卸载不完全,重装的一个下午

    玩软件就是随时面临着重新来过的危险.今天一不小心就把VM给高爆了,爆的很高的那种. 卸载不完全的VM如何在不重装系统的情况下安装. 首先第一步,肯定是通过控制面板去卸载VM,但是....但是...我靠 ...

  6. Java成长第四集--文本处理IO流

    Java IO流在实际业务中使用的频率还是蛮高的,一些业务场景比如,文件的上传和导出,文件的读取等基本都是通过操作IO流来实现的,所以IO流是我们现在学习过程中必须要掌握的技能之一,熟练的使用IO流, ...

  7. for循环,for…in循环,forEach循环的区别

    for循环,for…in循环,forEach循环的区别for循环通关for循环,生成所有的索引下标for(var i = 0 ; i <= arr.length-1 ; i++){ 程序内容 } ...

  8. 字符串的常用操作和方法(Python入门教程)

    字符串的常用操作 很好理解 字符串可以用 ' + ' 连接,或者乘一个常数重复输出字符串 字符串的索引操作 通过一对中括号可以找到字符串中的某个字符 可以通过正负数双向操作噢 用一个中括号来实现 为什 ...

  9. 关于树的重心--POJ 1655

    树的重心的定义: 在一棵树中,找到一个点,其所有的子树中最大的子树节点数最少,那么这个点就是这棵树的重心,删去重心后,生成的多棵树尽可能平衡. 通俗来说就是以这个点为根节点,找到他最大的衣蛾子树,然后 ...

  10. GNU的make命令、makefile编写

    makefile简介 makefile可实现工程的自动化编译,只需一个make命令即可一键完成.makefile定义了一些规则,指定哪些文件需要先编译.后编译.重新编译等. 一般的C或者C++程序,都 ...