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

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

        条件编译命令最常见的形式为

        #ifdef 标识符

        程序段1

        #else

        程序段2

        #endif

        

        它的作用是:当标识符已经被定义过(一般是用#define命令定义),则对程序段1进行编译,否则编译程序段2

        其中#else部分也可以没有,即:

        #ifdef

        程序段1

        #denif

        

        这里的“程序段”可以是语句组,也可以是命令行。这种条件编译可以提高C源程序的通用性。如果一个C源程序在不同计算机系统上运行,而不同的计算机又有一定的差异。例如,我们有一个数据类型,在Windows平台中,应该使用long类型表示,而在其他平台应该使用float表示,这样往往需要对源程序作必要的修改,这就降低了程序的通用性。可以用以下的条件编译:

        #ifdef WINDOWS

        #define MYTYPE long

        #else

        #define MYTYPE float

        #endif

        

        如果在Windows上编译程序,则可以在程序的开始加上

        #define WINDOWS

        

        这样则编译下面的命令行:

        #define MYTYPE long

        

        如果在这组条件编译命令之前曾出现以下命令行:

        #define WINDOWS 0

        

        则预编译后程序中的MYTYPE都用float代替。这样,源程序可以不必作任何修改就可以用于不同类型的计算机系统。当然以上介绍的只是一种简单的情况,可以根据此思路设计出其它的条件编译。

        例如,在调试程序时,常常希望输出一些所需的信息,而在调试完成后不再输出这些信息。可以在源程序中插入以下的条件编译段:

        #ifdef DEBUG

        print ("device_open(%p) ", file);

        #endif

        

        如果在它的前面有以下命令行:

        #define DEBUG

        

        则在程序运行时输出file指针的值,以便调试分析。调试完成后只需将这个define命令行删除即可。有人可能觉得不用条件编译也可达此目的,即在调试时加一批printf语句,调试后一一将printf语句删除去。的确,这是可以的。但是,当调试时加的printf语句比较多时,修改的工作量是很大的。用条件编译,则不必一一删改printf语句,只需删除前面的一条“#define DEBUG”命令即可,这时所有的用DEBUG作标识符的条件编译段都使其中的printf语句不起作用,即起统一控制的作用,如同一个“开关”一样。

        有时也采用下面的形式:

        #ifndef 标识符

        程序段1

        #else

        程序段2

        #endif

        

        只是第一行与第一种形式不同:将“ifdef”改为“ifndef”。它的作用是:若标识符未被定义则编译程序段1,否则编译程序段2。这种形式与第一种形式的作用相反。

        以上两种形式用法差不多,根据需要任选一种,视方便而定。

        还有一种形式,就是#if后面的是一个表达式,而不是一个简单的标识符:

        #if 表达式

        程序段1

        #else

        程序段2

        #endif

        

        它的作用是:当指定的表达式值为真(非零)时就编译程序段1,否则编译程序段2。可以事先给定一定条件,使程序在不同的条件下执行不同的功能。

        例如:输入一行字母字符,根据需要设置条件编译,使之能将字母全改为大写输出,或全改为小写字母输出。

        #define LETTER 1

        main()

        {

        char str[20]="C Language",c;

        int i="0";

        while((c=str[i])!='\0'){

        i++;

        #if LETTER

        if(c>='a'&&c<='z') c="c-32";

        #else

        if(c>='A'&&c<='Z') c="c"+32;

        #endif

        printf("%c",c);

        }

        }

        

        运行结果为:C LANGUAGE

        现在先定义LETTER1,这样在预处理条件编译命令时,由于LETTER为真(非零),则对第一个if语句进行编译,运行时使小写字母变大写。如果将程序第一行改为:

        #define LETTER 0

        

        则在预处理时,对第二个if语句进行编译处理,使大写字母变成小写字母(大写字母与相应的小写字母的ASCII代码差32)。此时运行情况为:c language

        另外还有#elif

        #elif 使您得以创建复合条件指令。如果前面的 #if 和前面的任何 #elif(可选)指令表达式的计算结果都不是 true,则将计算 #elif 表达式。如果 #elif 表达式计算为 true,编译器将计算位于 #elif 和下一个条件指令之间的所有代码。例如:

        #define VC7 //...

        #if debug

        Console.Writeline("Debug build");

        #elif VC7 Console.Writeline("Visual Studio 7");

        #endif

        可以使用运算符 ==(相等)、!=(不相等)、&&(与)及 ||(或)来计算多个符号。还可          以用括号将符号和运算符分组。

        #elif 等效于使用:

        #else #if

        使用 #elif 更简单,因为每个 #if 都需要一个 #endif,而 #elif 即使在没有匹配的 #endif 时也可以使用。

        有人会问:不用条件编译命令而直接用if语句也能达到要求,用条件编译命令有什么好处呢?的确,此问题完全可以不用条件编译处理,但那样做目标程序长(因为所有语句都编译),而采用条件编译,可以减少被编译的语句,从而减少目标的长度。当条件编译段比较多时,目标程序长度可以大大减少。

     

    浅谈#ifdef在软件开发中的妙用

      笔者从事UNIX环境下某应用软件的开发与维护工作,用户分布于全国各地,各用户需要的基本功能都是一样的,但在某些功能上要随着需求变化,不断加以升级,要想实现全国各地用户的升级工作是很困难的,而我们则只是利用E-mail发送补丁程序给用户,这些补丁程序都是在一套软件的基础上不断地修改与扩充而编写的,并由不同的标志文件转入到不同的模块,虽然程序体积在不断扩大,但丝毫不影响老用户的功能,这主要是得益于C程序的#ifdef/#else/#endif的作用。

     

      我们主要使用以下几种方法,假设我们已在程序首部定义#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的定义并重新编译,即可发给用户使用了。

    # ifdef  #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中成功编译。

    结论:

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

    (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文件中

    展开全文
  • 这种情况可能在多个文件中使用了条件编译,但是编译工程的时候又只是编译了部分文件,即使有部分使用了条件编译的文件没有被重新编译。 解决办法:1.把所有使用了条件编译的文档全部编译一遍;2.把工程全部编译一...

    在工程中定义了几个条件编译,用来适应不同的硬件设备,但是好像不起作用似的。这种情况可能是在多个文件中使用了条件编译,但是编译工程的时候又只是编译了部分文件,即使有部分使用了条件编译的文件没有被重新编译。

    解决办法:1.把所有使用了条件编译的文档全部编译一遍;2.把工程全部编译一遍。

    展开全文
  • 条件编译

    2018-04-02 12:45:53
    什么是条件编译 —般情况下,C语言源程序中的每一行代码都要参加编译。但有时候出于对程序代码优化的考虑,希望只对其中一部分内容进行编译。此时就需要在程序中加上条件,让编译器只对满足条件的代码进行编译,将...

    什么是条件编译

    —般情况下,C语言源程序中的每一行代码都要参加编译。但有时候出于对程序代码优化的考虑,希望只对其中一部分内容进行编译。此时就需要在程序中加上条件,让编译器只对满足条件的代码进行编译,将不满足条件的代码舍弃,这就是条件编译(conditional compile)。
    不用条件编译命令而直接用if语句也能达到要求,那么用条件编译命令有什么好处呢?的确,很多问题完全可以不用条件编译处理,但那样做目标程序长(因为所有语句都编译)。而采用条件编译,可以减少被编译的语句,从而减少目标的长度。当条件编译段比较多时,目标程序长度可以大大减少。

    条件编译的命令主要包括以下:

    #define       定义一个预处理宏
    #undef        取消宏的定义
    
    #if           编译预处理中的条件命令,相当于C语法中的if语句
    #ifdef        判断某个宏是否被定义,若已定义,执行随后的语句
    #ifndef       与#ifdef相反,判断某个宏是否未被定义
    #elif         若#if, #ifdef, #ifndef或前面的#elif条件不满足,则执行#elif之后的语句,相当于C语法中的else-if
    #else         与#if, #ifdef, #ifndef对应, 若这些条件不满足,则执行#else之后的语句,相当于C语法中的else
    #endif        #if, #ifdef, #ifndef这些条件命令的结束标志.
    defined       与#if, #elif配合使用,判断某个宏是否被定。

    条件编译的好处

    1.可通过编译器命令行定义预处理器使用的宏 。
    2.条件编译可以避免重复包含同一个头文件 。
    3.条件编译在工程开发中可以区别不同产品线的代码 。
    4.条件编译可以定义产品的发布版和调试版。

    条件编译的用途解析

    宏定义

    可使用#define和#undef定义及取消定义一个宏。

    宏定义,按照是否带参数通常分为对象宏、函数宏两种。
    对象宏: 不带参数的宏被称为”对象宏(objectlike macro)”。对象宏多用于定义常量、通用标识。
    例如:

    // 常量定义
    #define MAX_LENGTH 100
    // 通用标识,日志输出宏
    #define SLog printf
    // 预编译宏
    #define _DEBUG

    函数宏:带参数的宏。
    利用宏可以提高代码的运行效率:子程序的调用需要压栈出栈, 这一过程如果过于频繁会耗费掉大量的CPU运算资源。 所以一些代码量小但运行频繁的代码如果采用带参数宏来实现会提高代码的运行效率。但多数c++程序不推荐使用函数宏,调试上有一定难度,可考虑使用c++的inline代替之。例如:

    // 最小值函数
    #define MIN(a,b) ((a)>(b)? (a):(b))
    // 安全释放内存函数
    #define SAFE_DELETE(p) {if(NULL!=p){delete p; p = NULL;}}

    #undef可以取消宏定义,与#define对应。

    防止重复包含头文件

    #include的本质是将已经存在的文件内容嵌入到当前文件中。
    #include的间接包含同样会产生嵌入文件内容的动作。
    因此,可能会出现某一个头文件被多次包含的情况,这样可能会产生错误。
    如果使用条件编译,可以随心所欲的包含头文件。

    #ifndef _HEADER_H_
    #define _HEADER_H_
        //头文件的内容
    #endif

    不同的产品线共用一份代码&区分编译产品的调试版和发布版

    举例说明:

    #include <stdio.h>
    
    #ifdef DEBUG
        #define LOG(s) printf("[%s:%d] %s\n", __FILE__, __LINE__, s)
    #else
        #define LOG(s) NULL
    #endif
    
    #ifdef HIGH
    void f()
    {
        printf("This is the high level product!\n");
    }
    #else
    void f()
    {
    }
    #endif
    
    int main()
    {
        LOG("Enter main() ...");
    
        f();
    
        printf("1. Query Information.\n");
        printf("2. Record Information.\n");
        printf("3. Delete Information.\n");
    
        #ifdef HIGH
        printf("4. High Level Query.\n");
        printf("5. Mannul Service.\n");
        printf("6. Exit.\n");
        #else
        printf("4. Exit.\n");
        #endif
    
        LOG("Exit main() ...");
    
        return 0;
    }

    对于上面的程序,使用gcc -DDEBUG test.c 可以编译调试版。使用gcc -DHIGH test.c 可以编译高级版本。
    加上-D选项就是在编译时增加对-D后面的宏的定义。也可以用-D name=definition,来通过命令窗口对宏进行定义。
    gcc还有与-D对应的另一个参数-U用于取消宏。

    补充

    defined

    defined用来测试某个宏是否被定义。defined(name): 若宏被定义,则返回1,否则返回0。
    它与#if、#elif、#else结合使用来判断宏是否被定义,乍一看好像它显得多余, 因为已经有了#ifdef和#ifndef。defined可用于在一条判断语句中声明多个判别条件;#ifdef和#ifndef则仅支持判断一个宏是否定义。

    #if defined(VAX) && defined(UNIX) && !defined(DEBUG) 

    和#if、#elif、#else不同,#ifdef、#ifndef、defined测试的宏可以是对象宏,也可以是函数宏。

    #if

    常量表达式可以是包含宏、算术运算、逻辑运算等等的合法C常量表达式,如果常量表达式为一个未定义的宏,那么它的值被视为0。

    #if MACRO_NON_DEFINED 
    // 等价于
    #if 0

    在判断某个宏是否被定义时,应当避免使用#if,因为该宏的值可能就是被定义为0。而应当使用#ifdef或#ifndef。

    注意:#if、#elif之后的宏只能是对象宏。如果宏未定义,或者该宏是函数宏,则编译器可能会有对应宏未定义的警告。

    参考:
    1.https://blog.csdn.net/qq_33658067/article/details/79443014
    2.https://blog.csdn.net/qq_36016407/article/details/54946352
    3.https://blog.csdn.net/joeblackzqq/article/details/6785256

    展开全文
  • 经常在项目中能看到条件编译的代码,意思我能读懂,但我不知道为什么用这个?这个一般什么情况下用啊
  • 总会碰到很多不懂的地方第一时间上网搜答案,就比如在uni-app模版看到的#ifdef MP,这是什么鬼? 对于学过C语言的童鞋并不陌生,因为这是条件编译语句 为什么会出现在uni-app里呢?因为uni-app的特性---一份代码,...

    uni-app官方文档传送门:条件编译(点我)

    相信很多刚接触uni-app的童鞋都不太喜欢先看完整官方文档。总会碰到很多不懂的地方第一时间上网搜答案,就比如在uni-app模版看到的#ifdef MP,这是什么鬼?

    对于学过C语言的童鞋并不陌生,因为这是条件编译语句

    为什么会出现在uni-app里呢?因为uni-app的特性---一份代码,多平台运行。没错,就是一套代码,可以在android ios 各个小程序和h5上运行,因此为了代码简洁性引入的条件编译,

    #ifdef   #ifndef  #endif(其实官网介绍的也很详细)

    标准的语法

    // #ifdef %PLATFORM%
        %PLATFORM%为平台名称
        这里的内容只会编译在该平台
    // #endif

    可以看到其实以#ifdef开头 #endif结尾,但是注意一下就会发现前面双斜杠,这里是注释标记

    也就是说在各个代码块里的注释不一样,注释标记就要切换掉,比如

    js:  // #ifdef
    tag标签: <!--  #ifdef  -->
    css样式: /*  #ifdef  */

    解释一下语句是什么意思

    #ifdef :       if defined  仅在某个平台编译

    #ifndef :     if not defined  在除里该平台的其他编译

    #endif :       end if 结束条件编译

    %PLATFORM%       需要编译的平台,上面的MP就是各个小程序的意思

    uni-app支持的各个平台(下面官网copy过来的)

    平台 参考文档
    APP-PLUS 5+App HTML5+ 规范
    APP-PLUS-NVUE 5+App nvue Weex 规范
    H5 H5  
    MP-WEIXIN 微信小程序 微信小程序
    MP-ALIPAY 支付宝小程序 支付宝小程序
    MP-BAIDU 百度小程序 百度小程序
    MP-TOUTIAO 头条小程序 头条小程序
    MP-QQ QQ小程序 (目前仅cli版支持)
    MP 微信小程序/支付宝小程序/百度小程序/头条小程序/QQ小程序  

    示例 如果只需要在微信小程序上编译某段代码的话

    // #ifdef MP-WEIXIN
        我是那个代码
    // #endif

     

    展开全文
  • 条件编译初步

    2019-07-13 15:19:56
    一直以来不知道条件编译什么卵用,也不会用条件编译,最近看《算法竞赛入门经典》时,又接触到了这个概念,便稍微学了一点,于是积累下来,记作一篇经验。 首先是条件编译的概念: 顾名思义,在某些条件下进行...
  • uni-app 已将常用的组件、JS API 封装到框架中,开发者按照 uni-app 规范开发即可保证多平台兼容,大部分业务均可直接满足。 但每个平台有自己的...编译到不同的工程后二次修改,会让后续升级变的很麻烦。在 C 语...
  • 什么下面这段代码会输出"IF" #include int main() { #if (a==0) printf( "IF"); #else printf("ELSE"); #endif return 0; }
  • 实验1 :条件编译是什么 实验2 : 通过命令行 定义宏 情景1 :定义宏代表一个值 情景2:定义宏代表一个标识符是否存在。仅仅是定义一个宏,但是不给他赋值,宏和变量是不同的,宏可以代表一个值,他也可以仅仅表示一...
  • 条件编译#if

    2017-04-26 09:43:36
    1、为什么需要条件编译 客户的需求在不停地发生变化,一会儿需要这个功能,一会儿不需要这个功能。我们可以使用条件编译来方便地裁剪功能。 2、条件编译语句#if 条件编译语句#if的形式 1 #if expression 2 .....
  • 文章目录什么是交叉编译维基百科百度百科什么是条件编译维基百科百度百科golang中使用交叉编译golang使用条件编译实际应用总结参考文档 什么是交叉编译 先给出维基百科和百度百科解释(tips:维基百科只有交叉编译器...
  • C# #define条件编译详解

    2020-08-31 19:10:00
    主要介绍了C# #define条件编译,告诉大家#define用来做什么?如何使用#define,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • uni-app条件编译

    2021-06-11 08:50:33
    js: // #ifdef tag标签: <!-- #ifdef --> css样式: /* #ifdef */ ...#endif :end if 结束条件编译 %PLATFORM%需要编译的平台,上面的MP就是各个小程序的意思 uni-app支持的各个平台(下面官网...
  • 18.4 条件编译

    2019-02-17 18:32:00
    18.4.1 #if 0…#endif的用途... 可是为什么不用注释符号/*?  答:为了解决嵌套注释。例子如下: #include“stdio.h” int main(){  int a=11;  /*这一个外层注释 /* int *b=&a; //这一个...
  • 使用#if(条件1)#else 条件编译的时候,当#if(条件1)中的条件对比内容枚举成员的时候会出现无论什么情况,#if后边的条件都真的情况。这可能由于#if条件起作用在预编译阶段起作用,而预编译阶段时候枚举变量...
  • 巧用C语言中的条件编译

    千次阅读 2017-07-08 10:24:35
    相信接触过C语言的同学对条件编译都比较熟悉,而对于初学者来说估计都会抛出“什么是条件编译条件编译的作用以及编写方法怎样的”下面就为大家详细介绍C语言中的条件编译的概念和作用以及用法。  所谓...
  • 比如我们在同一份代码中,编译出debug版本和release版本,debug版本中就可以打印出调试的时候需要的一些日志,参数什么的,但是正式版本就不能有这些日志,那么这个方法将特别有效的一种解决途径。下边先看一个...
  • 条件编译指令#ifndef

    2019-01-17 14:24:27
    条件编译指令组合起来有几种不同的形式,实现不同的用途。 可以让一个源程序在不同的编译条件下产生不同的目标代码。 下面介绍一种经常出现的情况: 比如有一个头文件叫head.h 会看到有些程序写成这样: #ifndef ...
  • 什么是编译

    2010-09-04 09:23:00
     处理#开头的指令,比如拷贝#include包含的文件代码,#define宏定义的替换,条件编译等  就是为编译做的预备工作的阶段  主要处理#开始的预编译指令  预编译指令指示了在程序正式编译前就由编译器...
  • 什么是编译?何时需要预编译

    千次阅读 2018-01-30 16:40:44
    处理以# 开头的指令 , 比如拷贝 #include 包含的文件代码,#define 宏定义的替换 , 条件编译等,就是为编译做的预备工作的阶段。 主要处理#开始的预编译指令,预编译指令指示了在程序正式编译前就由编译器...
  • 如拷贝#include包含的文件代码、替换#define定义的宏、条件编译#if等。. 何时需要预编译: 1、总是使用不经常改动的大型代码体。 2、程序由多个模块组成,所有模块都使用一组标准的包含文件和相同的编译选项。在这种...
  • Flex编译器支持条件编译

    千次阅读 2008-04-28 14:54:00
    Flex编译器支持条件编译 RJ Owen条件编译允许我们告诉编译器选择性的不编译给定一部分代码除非我们给定的特定条件满足才对该部分进行编译,显然这在FLEX3中ADOBE刚刚推出的新特性,之前我都没有听说过,知道今天...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,891
精华内容 756
关键字:

条件编译是什么