首页 > 其他分享 >C-条件编译、头文件

C-条件编译、头文件

时间:2023-09-09 10:33:57浏览次数:52  
标签:__ ... 头文件 printf 编译 endif 条件 define

一、条件编译

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

查看预处理的结果:

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

标签:__,...,头文件,printf,编译,endif,条件,define
From: https://www.cnblogs.com/ljf-0804/p/17688996.html

相关文章

  • 空指针产生的条件 null对象调用属性
    null对象调用属性 e.gpublicclassStudent{Integerage;Stringname;Stringaddress;Useruser;}Studentstudent=newStudent();12:student.getUser().getName()Exceptioninthread"main"java.lang.NullPointerException atpatter......
  • rdkafka编译
    1、下载源码rakafka源码https://github.com/confluentinc/librdkafka 2、安装openssl,可以参考https://www.cnblogs.com/ho966/p/15916018.html3、如果要支持gssapi,需要依赖cyrus-sasl和krb53.1安装krb5下载源码https://kerberos.org/dist/krb5/1.20/krb5-1.2......
  • 安防教育直播项目应用中RTSPSever组件libEasyRTSPServer编译arm版本报undefined refer
    大家知道我们团队编译过很多产品的ARM版本,对用户来说,多一种编译方式也是多一种选择,所以我们一直在拓宽TSINGSEE青犀视频全线产品的运用范围。近期TSINGSEE青犀视频研发团队编译了libEasyRTSPServer的ARM版本,在此过程中,我们遇到了编译错误undefinedreferenceto`uselocale’。libE......
  • MacOs环境反编译微信小程序
    条件:mac版微信版本大于3.8.0的(无需解*密,下面直接反编译)使用node版本的wxappUnpacker解*密工具(https://github.com/geilige/wxappUnpacker)步骤:打开微信小程序,点点点点点点(尽量点全)默认存放小程序的路径/Users/用户名/Library(资源库)/Containers/com.tencent.xinWeChat(微信)/Data/.wxap......
  • gcc 常见编译参数
    -c只激活预处理,编译,和汇编-S只激活预处理和编译-E只激活预处理-C在预处理的时候,不删除注释信息-g只是编译器,产生调试信息。-o制定目标名称-w不生成任何警告信息。-M生成文件关联的信息。......
  • C#_防止SQL注入的参数化格式Where条件
    publicclassWhereBuilder{privatereadonlyStringBuilder_whereBuilder=newStringBuilder();privatereadonlyList<SugarParameter>_parameter=newList<SugarParameter>();publicvoidAppend(strings)=>Append(s,null,null......
  • Apktool编译时报error: No resource identifier found for attribute XXX in package
    问题描述使用apktool编译android源码时,报W:XXX.xml:X:error:Noresourceidentifierfoundforattribute'iconTint'inpackage'android'错误。解决方案这是由于API版本较低。处理方法:找到相应文件,把对应的属性删除掉,再重新编译。......
  • qt程序调用cuda-11.7,cmake编译时,提示:"CMakeCUDACompilerId.cu" failed. Compiler:
    报错显示:Running/home/wc/software/cmake-3.26.3-linux-x86_64/bin/cmake/home/wc/work/junke_src/missile-sim'-GCodeBlocks-UnixMakefiles'in/home/wc/work/junke_src/build/debug.CMakeErrorat/home/wc/software/cmake-3.26.3-linux-x86_64/share/cmak......
  • IDEA编译报错:maven-resources-production:guyi-admin: java.lang.IndexOutOfBoundsExc
    编译项目的时候,IDEA一直提示:maven-resources-production:xxxxxx:java.lang.IndexOutOfBoundsException:Range[-1,-1+1025)outofboundsforlength1024,maven-resources-production:xxxxxx:java.lang.IndexOutOfBoundsException:Range[-1,-1+1025)outofboundsfor......
  • 安全认证 | CISP考试资格及报考条件
    在参加CISP考试之前我们准备好相关的工作对于拿证是有很大的帮助的。那么CISP考试资格及报考条件是什么?下面我们就来了解一下吧。01CISP考试资格及报考条件★报考条件CISP考试条件详情:满足CISP教育和工作经验要求注册资格(1)教育和工作经验要求:硕士以上学历,有一年以上工作经验;或......