c语言学习笔记(12)条件编译使用分析

本文详细阐述了条件编译与if..else语句的区别,如何通过预处理阶段的行为实现条件编译,并介绍了如何使用条件编译避免在代码中重复包含头文件的问题。通过实例演示了在不同目标平台下如何利用条件编译简化代码。同时,文章解释了#include的本质及其可能导致的重复包含问题,并提供了条件编译解决这一问题的方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

摘要:总结了条件编译和if else的区别,#include在包含头文件时候的注意点,使用条件编译避免重复包含头文件,最后给出一个实例加深理解。


一、什么是条件编译 

    我们在移植u-boot和linux内核的时候,经常会看到#ifdef…#endif或者#ifndef…#endif这样的代码,这个就是条件编译,总的来说:

    1.条件编译行为类似if…else,都是条件成立做什么事,不成立就不做什么事。

    2.条件编译是作用在预处理阶段的指示命令,用于控制是否编译某段代码,这也是它和if..else不同的地方。


二、条件编译和if…else语句的区别

    通俗的解释一下,就是条件编译在预处理阶段,根据#if后面的条件是否成立,来判断哪些代码会被编译进去,哪些不会编译,经过条件编译之后,我们的编译器是看不到那些不成立部分的代码的。而if。。else是要在程序运行的时候进行值的判断,编译器是要对if 和else两个部分的代码都要进行编译。举个例子如下:

#include<stdio.h>
 
#define c 1
 
int main(void)
{
    #if(c==1)
    {
       printf("happytiaojianbianyi!\n");
       }  
    #else
    {
       printf("tiaojianbianyiis not happy!\n");
       }
    #endif
   
    if(c==1)
       {
           printf("happyif else!\n");
           }
    else
       {
           printf("ifelse is not happy!\n");
           }
          
    return0;
}

    接着,我们先生成预编译阶段的代码,在编译运行:

    #gcc–E test1.c –o test1.i

    得到的text1.i文件如下;

#2 "test1.c" 2
 
 
 
int main(void)
{
 
 {
 printf("happy tiaojianbianyi!\n");
 }
 
 
 
 
 
 
 if(1==1)
 {
  printf("happy if else!\n");
  }
 else
 {
  printf("if else is not happy!\n");
  }
 
 return 0;
}

    红色字体是要注意的部分,可以很明显的看到,在预编译阶段,条件编译把不成立的部分直接去掉了,而if和else则被完全保留了下来,这就是最直接的差别,条件编译会根据不同的目标平台做改变,比如我们要移植mini2440的u-bot,那么我们就在相关文件里面#define MINI2440_CONFIG,这样我们在编译的时候就会大大的简化代码,接着编译运行:

    #gcc test1.c –o test1

    得到的结果如下:

    #happytiaojianbianyi!

    #happyif else!

    结果都是可以预计的,但是过程是不同的。


三、编译阶段定义宏

    刚才的例子,我们在文件的顶部加了一句

    #definec 1

    但是我们在编译的时候,想要看等于0的情况,如果每次都去修改代码会比较麻烦,这时候就可以借助编译器的功能,这时候我们把原来程序里面宏定义的部分给注释掉,如下:

    //#definec 1

    接着,按照如下方法编译:

    #gcc –DC=0 test1.c –o test

    这时候出现的结果就变成了如下:

    #tiaojianbianyiis not happy!

    #ifelse is not happy!

    说明我们在编译的时候,指定的宏定义已经生效了。


四、#include的本质

    1.include的本质是将已经存在的文件内容嵌入到当前文件中。这句话说明意思呢?就是说,比如我们在程序里面,直接使用了printf这个函数,这个函数我们没有定义啊,怎么来的呢?就是因为我们#include<stdio>这个头文件,这个头文件里面是标准的输入输出文件,里面已经为我们写好了各种各样的输入输出函数,所以我们在预编译的时候,前面会有一大段,就是stdio里面的东西。

    2.#include简介包含同样会产生嵌入文件的动作。比如,我们include”test.h”然后test.h里面又include”fun.h”,那么在我们的源文件里面就会把test.h和fun.h里面的内容都嵌入到我们的源文件里面去。这样就会引起什么问题呢?重复包含,重复包含一定是会报错的,试想一下你在一个文件里面两次定义一个函数,会不会报错,答案是肯定的。


五、条件编译解决include重复包含头文件

    其实原理很简单,就是在文件头加上两句话,意思是,如果我已经包含了某某头文件,那么久不要再包含了,举个例子:

    我们有三个文件;test2.c,test2.h和fun.h

    分别如下:

test2.c
#include <stdio.h>
#include "test2.h"
#include "fun.h"
 
int main(void)
{
    printf("%d\n",fun(2,3));
      
    return0; 
}
    test2.h
    #include"fun.h"
    fun.h
#ifndef _FUN_H_
#define _FUN_H_
 
int fun(int a,int b)
{
    returna+b;
    }
   
#endif

    文件很简单,红色字体是在重复添加头文件的时候需要加进去的,有时候我们可以直接去重复添加的头文件不就完了吗?但是在处理很大的项目的时候,我们并不能认为的保证我们添加的头文件或者函数没有被别的组定义,使用这个方法可以消除这个顾虑,这样就会判断我们是否已经包含了这个头文件,如果已经包含了,那就不在包含。


六、条件编译意义与总结

    1.条件编译可以产生不同的目标代码,在预编译阶段被处理,而if..else在程序运行的时候在做判断。

    2.条件编译可以用于不同的产品线共用一份代码,或者区分调试版和发布版。

    3.条件编译可以避免重复包含同一个头文件。

    这篇帖子就总结到这里,如有不正确的地方还请指出,大家共同进步!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值