C-条件编译、头文件

一、条件编译

根据条件(表达式的值或者特定的宏的值)决定让代码是否参与最终的编译

查看预处理的结果:

gcc -E code.c   把预处理的结果显示到终端

gcc -E code.c -o code.i 把预处理的结果存储到.i预处理文件

1、常见的条件编译指令

指令
#if 如果条件为真,则执行相应的操作。
#elif 类似于 elseif 的用法,当前面条件为假,再判断该条件是否为真,如果是真,则执行相应操作。
#else 如果前面所有条件均为假,则执行相应操作。
#ifdef 如果该宏已定义,则执行相应操作
#ifndef 如果该宏没有定义,则执行相应操作
#endif 结束对应的条件编译指令。(不能省略)

2、#if,#elif,#else与#endif

版本控制/注释代码

#if 常量表达式1
...
#elif 常量表达式2
...
#else 常量表达式3
...
#endif 

常量表达式可以是包含宏、算术运算、逻辑运算等等的合法C常量表达式,

如果常量表达式为一个未定义的宏, 那么它的值被视为0.即

#if MACRO_NON_DEFINED // 等价于

#if 0

实例:

#include <stdio.h>

#define VERSION 1
int main(int argc,const char* argv[])
{
#if VERSION > 2
    printf("最新版本!\n");
#elif VERSION > 1
    printf("还凑合!\n");
#else
    printf("赶紧升级!\n");
#endif
}
输出:赶紧升级!
gcc -E  xx.c  查看预处理文件,发现只编译了printf("赶紧升级!\n");  
  • 注释代码
#if 0
//代码1
#endif

实例:

#define VERSION 1
#if 0    //中间的代码不参与编译,就相当于注释代码
#if VERSION > 2
    printf("最新版本!\n");
#elif VERSION > 1
    printf("还凑合!\n");
#else
    printf("赶紧升级!\n");
#endif
#endif

3、#ifdef,#ifndef,#else与#endif

头文件卫士:防止头文件被重复包含,头文件必加

#ifndef 宏名    //如果宏不存在为真,头文件名的大写XX_H
#define 宏名
//
#endif //一般加上注释,表明是哪个头文件的endif   

实例:

head.h:
#ifndef HEAD_H
#define HEAD_H
extern int Num;
#endif//HEAD_H   

head.c:
#include <stdio.h>
#include "head.h"
int main(int argc,const char* argv[])
{
    printf("%d\n",Num);
}

4、#ifdef \ #else \ #endif

判断、调试:

#ifdef 宏名 //如果宏存在为真
#else
#endif        

在编译时添加宏DEBUG:gcc 02debug.c -DDEBUG

-D 在编译的时候临时定义一个宏

5、打印调试信息:

#ifdef DEBUG
     #define debug(...) printf(__VA_ARGS__)
#else
     #define debug(...)
#endif
//__VA_ARGS__被...的内容替换

6、打印错误信息:

#define error(...) printf("%s %s:%d %s %m %s %s\n",__FILE__,__func__,__LINE__,__VA_ARGS__,__DATE__,__TIME__)
%m 错误信息

实例:

#include <stdio.h>

#ifdef DEBUG
    #define debug(...) printf(__VA_ARGS__)
#else
    #define debug(...)
#endif

#define error(...) printf("%s %s:%d %s %m %s %s\n",__FILE__,__func__,__LINE__,__VA_ARGS__,__DATE__,__TIME__)

int main(int argc,const char* argv[])
{
    FILE* fp = fopen("hehe","r");
    if(NULL == fp)
    {
        error("fopen");
        return 0;
    }
    printf("success\n");
    return 0;

    int num = 0;
    int ret = scanf("%d",&num);
    debug("ret=%d\n",num);
}

二、头文件

头文件中应该写什么:

头文件可能会被任意源文件包含,意味着头文件中的内容可能会在多个目标文件中存在,要保证合并时不要冲突

重点:头文件只编写声明语句,不能有定义语句

  • 全局变量声明

  • 函数声明

  • 宏常量

  • 宏函数

  • typedef 类型重定义

  • 结构、枚举、联合的类型设计声明

头文件的编写规则:

1、为每个.c文件写一份.h文件,.h文件是对它对应的.c文件的说明

2、如果需要用到某个.c文件中的变量、函数、宏时,只需要把该文件的.h文件导入即可

3、.c文件也要导入自己的.h文件,目的是为了让定义与声明保持一致

头文件的相互包含:

假如a.h包含了b.h的内容,而b.h中又包含了a.h的内容,这时就会产生头文件的相互包含,无法编译通过

解决方案:把a.h中需要b.h的内容,和b.h中需要a.h的内容提取出来,额外再写另一个c.h

posted @   冲他丫的  阅读(107)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 上周热点回顾(3.3-3.9)
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
点击右上角即可分享
微信分享提示