C温故补缺(十二):预编译器与头文件
预编译器
预编译器就是之前学的预编译指令的执行者
gcc -E test.c -o test.i
生成预编译文件就是翻译#指令
比如#include<stdio.h>就是把整个stdio.h头文件和项目文件连接
所用预编译指令
| #define | 定义宏 |
|---|---|
| #include | 包含一个源代码文件 |
| #undef | 取消已定义的宏 |
| #ifdef | 如果宏已经定义,则返回真 |
| #ifndef | 如果宏没有定义,则返回真 |
| #if | 如果给定条件为真,则编译下面代码 |
| #else | #if 的替代方案 |
| #elif | 如果前面的 #if 给定条件不为真,当前条件为真,则编译下面代码 |
| #endif | 结束一个 #if……#else 条件编译块 |
| #error | 当遇到标准错误时,输出错误消息 |
| #pragma | 使用标准化方法,向编译器发布特殊的命令到编译器中 |
error用来提示预编译的错误,当程序执行的#error时,输出信息,停止编译后续代码
如:
// #define a 10
#ifndef a
#error Const Variable a not defined
#endif

把第一行注释取消,

就预编译成功了

预编译宏
| 宏 | 描述 |
|---|---|
| DATE | 当前日期,一个以 "MMM DD YYYY" 格式表示的字符常量。 |
| TIME | 当前时间,一个以 "HH:MM:SS" 格式表示的字符常量。 |
| FILE | 这会包含当前文件名,一个字符串常量。 |
| LINE | 这会包含当前行号,一个十进制常量。 |
| STDC | 当编译器以 ANSI 标准编译时,则定义为 1。 |
这些预编译的宏都是可以直接输出的
如
#include <stdio.h>
int main(){
printf("File :%s\n", __FILE__ );
printf("Date :%s\n", __DATE__ );
printf("Time :%s\n", __TIME__ );
printf("Line :%d\n", __LINE__ );
printf("ANSI :%d\n", __STDC__ );
}

宏运算符
①宏延续运算符
如果定义的宏太长,可以用\来多行表示
#define The_total_number_\
of_students 50
②字符串常量化运算符
使用#把宏参数转化成字符串常量
#include<stdio.h>
#define sayHello(name) printf("Hello " #name)
int main(){
sayHello(Eve);
}

预编译,看预编译的结果:

③标记粘贴运算符
使用##把两个标记合成一个,一般用来组成变量
#include<stdio.h>
#define trans(n) printf("%d",message##n);
int main(){
int message313=0x0010;
trans(313);
}

查看预编译的结果:

④defined()运算符
defined用于判断宏是否定义,并返回真/假,一般和if连用,但ifdef和ifndef也能实现这样的效果
参数化的宏
CPP可以使用参数化的宏来模拟函数
如:
#define squre(x) ((x)*(x))
#include<stdio.h>
int main(){
printf("%d",squre(4));
}

头文件
建议把所有的常量、宏、系统全局变量和函数原型写在头文件中,在需要的时候随时引用这些头文件
引用头文件
引用系统头文件
#include<stdio.h>
用< >括起来的表示系统环境中的头文件
用" "括起来的表示用户头文件
#include"func.h"
预编译
test.c
#include"func.h"
int main(){
int arr[10];
}
func.h
#define Total 0
#define PI 3.142
int Best_item=0;
int getBest_item(int *);
预编译:

直接把头文件中的内容插入到.c代码中
只引用一次头文件
如果不小心引用了两次头文件,编译器就会处理两次,预编译文件中就会有两边头文件代码,可能会导致异常
#include"func.h"
int main(){
#include"func.h"
int arr[10];
}
预编译:

为了防止 这种情况,标准做法是将整个头文件放在条件语句中
#ifndef flag
#define flag
#define Total 0
#define PI 3.142
int Best_item=0;
int getBest_item(int *);
#endif
这样再编译就不会出现两遍了

这种结构就是C语言中的包装器#ifndef
C温故补缺(十二):预编译器与头文件的更多相关文章
- C学习笔记(9)--- 预处理器,头文件
1.预处理器: 预处理器不是编译器的组成部分,但是它是编译过程中一个单独的步骤.简言之,C 预处理器只不过是一个文本替换工具而已,它们会指示编译器在实际编译之前完成所需的预处理. 我们将把 C 预处理 ...
- C 预处理器、头文件、文件读写
预处理器 参考链接:https://www.runoob.com/cprogramming/c-preprocessors.html 预处理器是再变异之前做的一些工作 include 包含一个源文件代 ...
- 基础知识复习(二)——stdafx.h 头文件及x&(x-1)运算
今天好久没写过C++程序了,使用VS2013 新建空的控制台程序,结果自动生成了头文件和main 方法. 就了解了stdafx.h头文件的含义及用法. stdafx:standard Applicat ...
- 浅谈VC++中预编译的头文件放那里的问题分析
用C++写程序,肯定要用预编译头文件,就是那个stdafx.h.不过我一直以为只要在.cpp文件中包含stdafx.h 就使用了预编译头文件,其实不对.在VC++中,预编译头文件是指放到stdafx. ...
- katalon系列十二:自动化上传文件、下载文件
一.下载文件1.下载文件时,需要先设置好Chrome/Firefox下载路径.不弹出下载框等,大家先学习下在selenium下如何设置:https://www.cnblogs.com/fnng/p/7 ...
- 三十二、python操作XML文件
'''XML:模块 xml总结 1.解析 str 文件 tree,ElementTree,type root,Element,type2.操作 Element: tag,text,find,iter, ...
- Spring(十二)使用Spring的xml文件配置方式实现AOP
配置文件与注解方式的有非常大不同,多了非常多配置项. beans2.xml <?xml version="1.0" encoding="UTF-8"? & ...
- Yii2 使用十二 配合ajaxFileUpload 上传文件
1.js $("input#upload").change(function () { $.ajaxFileUpload({ url: '/members/web-members- ...
- Simulink仿真入门到精通(十二) Publish发布M文件
12.1 M文件的注释 使用%进行注释. 连续多行注释Ctrl+R,取消注释Ctrl+T. 12.2 Cell模式 在MATLAB脚本文件中使用连续两个注释符,开启一个新的Cell块,%%后空一格追加 ...
- (Python基础教程之十二)Python读写CSV文件
Python基础教程 在SublimeEditor中配置Python环境 Python代码中添加注释 Python中的变量的使用 Python中的数据类型 Python中的关键字 Python字符串操 ...
随机推荐
- 【读书笔记】C#高级编程 第九章 字符串和正则表达式
(一)System.String类 System.String是一个类,专门用于存储字符串,允许对字符串进行许多操作.C#提供了关键字string和相关的语法,以便使用这个类更轻松. 例子: 使用运算 ...
- 快速排序C语言版图文详解
算法原理:选一个数位基准,将序列分成两个部分,一边全是比它小序列,另一边全是比它大序列.然后再分别对比他小的序列和比再次进行基准分割.依次分割下去,得到一个有序的队列. 原理图示: 编辑 编辑 ...
- Docker 与 Containerd 并用配置
描述: 事实上,Docker 和 Containerd 是可以同时使用的,只不过 Docker 默认使用的 Containerd 的命名空间不是 default,而是 moby,此处为了更方便我们学习 ...
- kubernetes中部署kube-prometheus项目解决ControllerManager与Scheduler无法监控问题
文章转载自:https://www.kococ.cn/20210302/cid=697.html 一.问题描述 在部署 kube-prometheus 到 kubernetes 集群中总会遇到一个问题 ...
- Ceph 有关知识简介
Ceph 存储集群至少需要一个 Ceph Monitor 和两个 OSD 守护进程.而运行 Ceph 文件系统客户端时,则必须要有元数据服务器( Metadata Server ). Ceph OSD ...
- #Lua:Lua调用C++生成的DLL库
Lua调用C++生成的DLL库 本文参考了某大佬的博客,写得十分详细,推荐!!! 需求: 在之前的求解器中添加了Lua库,使得程序可以在Lua脚本中实现自定义函数功能,考虑到未来可能需要与第三方程序库 ...
- SVM公式详尽推导,没有思维跳跃。
假定数据集\(T=\{(x_1,y_1),(x_2,y_2),...,(x_n,y_n)\},x_n \in R_k, y_n \in \{1,-1\}\)线性可分,SVM的优化目标是: 优化一个超平 ...
- 【C++】从零开始的CS:GO逆向分析1——寻找偏移与基址的方法
[C++]从零开始的CS:GO逆向分析1--寻找偏移与基址的方法 前言:此文章主要用于提供方法与思路,fps游戏基本都能如此找偏移,文章里找的偏移比较少,主要用来演示寻找思路,文章的后记中会附一个 ...
- 通用 HTTP 签名组件的另类实现
1.初衷 开发中经常需要做一些接口的签名生成和校验工作,最开始的时候都是每个接口去按照约定单独实现,久而久之就变的非常难维护,因此就琢磨怎么能够写了一个比较通用的签名生成工具. 2.思路 采用链式调用 ...
- 手把手教你使用LabVIEW人工智能视觉工具包快速实现图像读取与采集(含源码)
目录 前言 一.工具包位置 二.图像采集与色彩空间转换 1.文件读写 2.实现图片读取 3.使用算子cvtColor实现颜色空间转换 三.从摄像头采集图像 1.Camera类 2.属性节点 3.实现摄 ...