一、条件编译
根据条件(表达式的值或者特定的宏的值)决定让代码是否参与最终的编译
查看预处理的结果:
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