预编译器

预编译器就是之前学的预编译指令的执行者

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温故补缺(十二):预编译器与头文件的更多相关文章

  1. C学习笔记(9)--- 预处理器,头文件

    1.预处理器: 预处理器不是编译器的组成部分,但是它是编译过程中一个单独的步骤.简言之,C 预处理器只不过是一个文本替换工具而已,它们会指示编译器在实际编译之前完成所需的预处理. 我们将把 C 预处理 ...

  2. C 预处理器、头文件、文件读写

    预处理器 参考链接:https://www.runoob.com/cprogramming/c-preprocessors.html 预处理器是再变异之前做的一些工作 include 包含一个源文件代 ...

  3. 基础知识复习(二)——stdafx.h 头文件及x&(x-1)运算

    今天好久没写过C++程序了,使用VS2013 新建空的控制台程序,结果自动生成了头文件和main 方法. 就了解了stdafx.h头文件的含义及用法. stdafx:standard Applicat ...

  4. 浅谈VC++中预编译的头文件放那里的问题分析

    用C++写程序,肯定要用预编译头文件,就是那个stdafx.h.不过我一直以为只要在.cpp文件中包含stdafx.h 就使用了预编译头文件,其实不对.在VC++中,预编译头文件是指放到stdafx. ...

  5. katalon系列十二:自动化上传文件、下载文件

    一.下载文件1.下载文件时,需要先设置好Chrome/Firefox下载路径.不弹出下载框等,大家先学习下在selenium下如何设置:https://www.cnblogs.com/fnng/p/7 ...

  6. 三十二、python操作XML文件

    '''XML:模块 xml总结 1.解析 str 文件 tree,ElementTree,type root,Element,type2.操作 Element: tag,text,find,iter, ...

  7. Spring(十二)使用Spring的xml文件配置方式实现AOP

    配置文件与注解方式的有非常大不同,多了非常多配置项. beans2.xml <?xml version="1.0" encoding="UTF-8"? & ...

  8. Yii2 使用十二 配合ajaxFileUpload 上传文件

    1.js $("input#upload").change(function () { $.ajaxFileUpload({ url: '/members/web-members- ...

  9. Simulink仿真入门到精通(十二) Publish发布M文件

    12.1 M文件的注释 使用%进行注释. 连续多行注释Ctrl+R,取消注释Ctrl+T. 12.2 Cell模式 在MATLAB脚本文件中使用连续两个注释符,开启一个新的Cell块,%%后空一格追加 ...

  10. (Python基础教程之十二)Python读写CSV文件

    Python基础教程 在SublimeEditor中配置Python环境 Python代码中添加注释 Python中的变量的使用 Python中的数据类型 Python中的关键字 Python字符串操 ...

随机推荐

  1. WebDriver常见操作

    本文当个记录贴,记录WebDriver常用的一些函数(含自己封装的函数) 让WebDriver使用浏览器用户设置 1 option = webdriver.ChromeOptions() 2 opti ...

  2. 使用kubeoperator安装的k8s集群以及采用的containerd容器运行时,关于采用的是cgroup 驱动还是systemd 驱动的说明

    使用kubeoperator安装的k8s集群,默认使用的是systemd驱动 # kubectl get cm -n kube-system NAME DATA AGE calico-config 4 ...

  3. 【前端必会】Prettier,有了ESlint,还要Prettier

    介绍 已经安装了ESLint为什么还要Prettier,主要是让ESLint专注于语法相关的验证,检查潜在问题.而代码格式化则有Prettier来接管 对比参考: https://baijiahao. ...

  4. 【前端必会】eslint搞起

    介绍 eslint进行代码审查,统一代码风格,预防潜在BUG 官网 https://eslint.bootcss.com/docs/user-guide/getting-started 安装 init ...

  5. Netty 学习(八):新连接接入源码说明

    Netty 学习(八):新连接接入源码说明 作者: Grey 原文地址: 博客园:Netty 学习(八):新连接接入源码说明 CSDN:Netty 学习(八):新连接接入源码说明 新连接的接入分为3个 ...

  6. SqlKata - 方便好用的 Sql query builder

    SqlKata查询生成器是一个用C# 编写的功能强大的Sql查询生成器.它是安全的,与框架无关.灵感来源于可用的顶级查询生成器,如Laravel Query Builder和 Knex. SqlKat ...

  7. C++面向对象编程之虚指针、虚表

    1.当编译器看到一个函数调用,有2个考量:静态绑定or动态绑定 静态绑定是"call xxx",xxx 是表示地址,call 是汇编语言的一个动作,它一定会调用到某个地址: 当符合 ...

  8. sg函数入门理解

    首先理解sg函数必须先理解mex函数 mex是求除它集合内的最小大于等于0的整数,例:mex{1,2}=0:mex{2}=0:mex{0,1,2}=3:mex{0,5}=1. 而sg函数是啥呢? 对于 ...

  9. P2680 [NOIP2015 提高组] 运输计划 (树上差分-边差分)

    P2680 题目的大意就是走完m条路径所需要的最短时间(边权是时间), 其中我们可以把一条边的权值变成0(也就是题目所说的虫洞). 可以考虑二分答案x,找到一条边,使得所有大于x的路径都经过这条边(差 ...

  10. POJ1681 Painter's Problem(高斯消元)

    题目看似与线性方程组无关,但可以通过建模转化为线性方程组的问题. 对于一块砖,刷两次是没有必要的,我们令x=1表示刷了一次,x=0没有刷,一共有n*n个,所以相当于有n*n个未知量x. 定义aij表示 ...