C语言-预处理与库
预处理、动态库、静态库
1. 声明与定义分离
一个源文件对应一个头文件
注意:
- 头文件名以
.h作为后缀头文件名要与对应的原文件名一致
例:
源文件:01_code.c
#include <stdio.h>
int num01 = 10;
int num02 = 20;
void add(int a, int b)
{int sum = a + b;printf("%d + %d = %d\n", a, b, sum);
}void mul(int a, int b)
{int mul = a + b;printf("%d + %d = %d\n", a, b, mul);
}
头文件:01_code.h
extern int num01;
extern int num02;
extern void add(int, int);
extern void mul(int, int);
测试文件:test.c
#include <stdio.h>
#include "01_code.h"int main(int argc, char const *argv[])
{printf("num01 = %d\n", num01);printf("num02 = %d\n", num02);add(10, 20);mul(10, 20);return 0;
}
编译:
命令:
gcc test.c 01_code.c./a.out输出:
num01 = 10 num02 = 20 10 + 20 = 30 10 + 20 = 30
2. 预处理
2.1 c语言编译过程
gcc -E hello.c -o hello.i 1、预处理
gcc -S hello.i –o hello.s 2、编译
gcc -c hello.s -o hello.o 3、汇编
gcc hello.o -o hello_elf 4、链接
1、预编译
- 将
.c中的头文件展开、宏展开生成的文件是.i文件2、编译
- 将预处理之后的
.i文件生成.s汇编文件3、汇编
- 将
.s汇编文件 生成.o文件4、链接
- 将
.o文件 链接成目标文件(即可执行文件)
预编译包含
展开头文件
定义头文件
选择性编译注意:预编译的内容以 # 开头
2.2 include
作用:展开头文件
语法:
#include <>
用
尖括号包含的头文件, 在 系统指定的路径下 找头文件#:表示预编译
#include ""
用
双引号包含头文件,先在当前目录下找 头文件,找不到,再到系统指定的路径下找
注意:
1、include 经常用来包含头文件,可以包含
.c文件,但是大家不要包含.c因为 include 包含的文件会在预编译被展开,如果一个.c 被包含多次,展开多次,会导致函数重复定义。所以不要包含.c 文件2、预处理只是对 include 等预处理操作进行处理,并
不会进行语法检查,这个阶段有语法错误也不会报错,第二个阶段即编译阶段才进行语法检查。
例:
#include "01_code.h"//等价于 下面, 即在源文件中展开下面代码extern int num01;
extern int num02;
extern void add(int, int);
extern void mul(int, int);
2.2 宏:define
作用:在预处理 处理定义 类似于 变量或函数的东西。即:宏是在预编译的时候进行替换 。
2.2.1 不带参宏
语法:
#define 宏名 值 //宏定义#undef 宏名 //取消宏定义
注意:
1、如果定义该类型的宏(不带参的宏),
值可以省略2、无需分号结束
3、在 宏定义后,取消定义前 可以使用
4、只能在
当前文件中使用
例:
#include <stdio.h>
#define PI 3.14
int main(int argc, char const *argv[])
{printf("pi = %f\n", PI);
#undef PI //取消宏定义return 0;
}
2.2.2 带参宏
语法:
#define 宏名(形参) 体
注意:
1、形参没有数据类型
2、
带参宏与带参函数的区别
宏:在
预编译时对其进行 替换,如果一个文件中多次使用宏,那意味着要替换多次,此时就需占用内存,所以占据的内存多
- 产生的预编译时期
- 占内存多
- 速度快
函数:在程序运行时在代码区存储一份,每次调用该函数都需在代码区寻找,将其放入栈内存中(压栈),当函数执行完毕后,从栈中移除(弹栈)
- 产生在运行时
- 占内存少
例:
#include <stdio.h>
#define ADD(a, b) a+b
#define MUL(a, b) a*b
#define MUL02(a, b) (a)*(b)
int main(int argc, char const *argv[])
{int sum = ADD(20, 30);printf("sum=%d\n", sum);int mul = MUL(20, 30);printf("mul=%d\n", mul);int mul02 = MUL(20+10, 30+10); //20 + 10 * 30 +10printf("mul=%d\n", mul02);int mul03 = MUL02(20+10, 30+10); //(20 + 10) * (30 + 10)printf("mul=%d\n", mul03);return 0;
}

2.2.3 小结
宏就是在
预编译时期对其进行替换不带参宏替换的是一个值
带参宏替换的是一段代码
2.3 选择性编译
作用:选择代码是否被编译
语法:

例1:判断存在
优点:节省内存,只加载需要的部分
#include <stdio.h>int main(int argc, char const *argv[])
{#ifdef XXXprintf("有定义宏名为XXX的宏\n");#elseprintf("没定义宏XXX\n");#endifreturn 0;
}


编译时定义宏:

例2:判断不存在,和头文件配合使用,防止多次引用头文件
#include <stdio.h>
#include "04_test.h"
#include "04_test.h"
int main(int argc, char const *argv[])
{#ifndef YYYprintf("1111\n");#elseprintf("2222\n");#endifreturn 0;
}
头文件:04_test.h
#ifndef TEST
#define TEST
extern int num;
//...
#endif
#ifndef 使用含义:
1、
第一次引用头文件,没有定义TEST宏,然后定义,再写头文件内容;2、假如
再次引用头文件时,第一次已经定义过TEST宏了,所以直接结束,啥也不干。
源码写法:

例3:判断是否成立
#include <stdio.h>
int main(int argc, char const *argv[])
{#if ScORE > 85printf("A\n");#elif ScORE > 70printf("B\n");#elif ScORE >= 60printf("c\n");#elseprintf("D\n");#endifreturn 0;
}

3. 库
概念:库也叫代码库,可以把一个些目标文件合并在一起方便使用。
3.1 分类
静态库
动态库
静态库、动态库的区别:

注意:
- 程序中引入的文件在动态库与静态库同时存在两份
- 静态编译程序引入静态库中的该文件
- 动态编译程序引入动态库中的该文件
3.2 编译命令
动态编译:
gcc 源文件名 -o 生成的可执行文件名
静态编译:
gcc -static 源文件名 -o 生成的可执行文件名
3.3 静态库
3.3.1 制作
gcc -c 源文件名.c -o 生成的二进制文件名.o
ar rc lib静态库名称.a 生成的二进制文件名.o
注意:
静态库起名的时候必须 以lib 开头以.a结尾
步骤:
-
新建文件夹:
06_code -
源文件:
myfun.c#include <stdio.h>void add(int a, int b) {printf("my_sum = %d\n", (a+b)); }void mul(int a, int b) {printf("my_mul = %d\n", (a*b)); } -
头文件:
myfun.hextern void add(int a, int b); extern void mul(int a, int b); -
制作

3.3.2 使用
情况1:使用静态库的文件与静态库 在同一文件夹下
命令:
gcc 源文件名 静态库名称 -o 生成的可执行文件名
测试文件:test01.c
#include <stdio.h>
#include "myfun.h" //可以不写,但是会报警告
int main(int argc, char const *argv[])
{add(10, 3);return 0;
}
编译:

情况2:使用静态库的文件与静态库 不在同一文件夹下
注意:
为了让静态库文件与其对应的头文件和使用静态库文件不在同一文件夹下,所以
创建includes与libs文件夹
includes文件用于存储头文件
libs文件夹存储静态库文件
mkdir includes mkdir libs mv myfun.h includes/ mv libmyfun.a libs/参数
-L 引用的静态库所在的路径 -l 静态库名, 去掉lib与.a -I 头文件所在路径命令
gcc 源文件名 -L 静态库所在的路径 -l 静态库名 -I 头文件所在路径 -o 生成的可执行文件名
情况3:静态库文件与对应的头文件 在系统文件夹下
系统库路径:
/usr/include 存储头文件 /usr/lib 或 /lib 存储库文件注意:
# 为了让静态库文件与其对应的头文件和系统文件夹下,所以需要移动 sudo mv includes/myfun.h /usr/include sudo mv libs/libmyfun.a /usr/lib命令:
gcc 源文件名 -l 静态库名 -o 生成的可执行文件名
3.4 动态库
3.4.1 制作
命令:
gcc -shared 源文件名 -o 生成的动态库文件名.so
3.4.2 使用
情况1:使用动态库的文件与动态库在同一文件夹下
命令:
gcc 源文件名 动态库名称 -o 生成的可执行文件名
情况2:使用动态库的文件与动态库不在同一文件夹下
命令:
gcc 源文件名 -L 动态库所在路径 -l 动态库名称 -I 头文件所在路径注意:
- 动态库名需要去掉前面的
lib与后面.so
情况3:静态库文件与对应的头文件在系统文件夹下
命令:
gcc 源文件名 -l 静态库名 -o 生成的可执行文件名
相关文章:
C语言-预处理与库
预处理、动态库、静态库 1. 声明与定义分离 一个源文件对应一个头文件 注意: 头文件名以 .h 作为后缀头文件名要与对应的原文件名 一致 例: 源文件:01_code.c #include <stdio.h> int num01 10; int num02 20; void add(int a, in…...
王道数据结构课后代码题p40 9.给定一个带表头结点的单链表,写出算法 : 按递增次序输出单链表中各结点的数据元素并释放结点 (c语言代码实现)
本题代码如下(有注释) void delete_min(linklist* head) {while ((*head)->next ! NULL)//循环到只剩下头节点{lnode* pre *head;//pre为元素最小结点的前驱结点指针lnode* p (*head)->next;//p为工作指针lnode* q;//指向被删除的结点while (p-…...
对系统的 Go 版本进行升级
方法一 直接升级系统的 Go 版本 注意以下操作仅适用于:amd64 架构的 Centos 系统。如果需要适配其他架构,需要自行编写代码实现。 手动执行: # 显示当前版本 go version # 查看环境变量 cat /etc/profile # 进入 go 的安装目录,…...
【从删库到跑路 | MySQL总结篇】事务详细介绍
个人主页:兜里有颗棉花糖 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 兜里有颗棉花糖 原创 收录于专栏【MySQL学习专栏】🎈 本专栏旨在分享学习MySQL的一点学习心得,欢迎大家在评论区讨论💌 目录 一、事务…...
七牛云1024创建节-赛后有感
距离比赛结束已经过去快半个月时间,七牛云又发起了有奖征文的活动,正好借此机会记录一下自己参加这次比赛的经历,感受和一些比赛的心得。 如何了解到的比赛信息 其实我很早就开始关注七牛云了,最早是在今年二三月的时候…...
CSS 选择器优先级,!important 也会被覆盖?
目录 1,重要性2,专用性3,源代码顺序 CSS 属性值的计算过程中。其中第2步层叠冲突只是简单说明了下,这篇文章来详细介绍。 层叠冲突更广泛的被称为 CSS选择器优先级计算。 为什么叫层叠冲突,可以理解为 CSS 是 Cascadi…...
关于src别名的配置之tsconfig.json配置
tsconfig.json {"compilerOptions": {"baseUrl": "./", // 解析非相对模块的基地址,默认是当前目录"paths": { //路径映射,相对于baseUrl"/*": ["src/*"] }} } ① "baseUrl": &…...
Mybatis如何执行批量操作
文章目录 Mybatis如何执行批量操作使用foreach标签 使用ExecutorType.BATCH如何获取生成的主键 Mybatis如何执行批量操作 使用foreach标签 foreach的主要用在构建in条件中,它可以在SQL语句中进行迭代一个集合。foreach标签的属性主要有item,index&…...
LeetCode 1094. 拼车:优先队列
【LetMeFly】1094.拼车:优先队列 力扣题目链接:https://leetcode.cn/problems/car-pooling/ 车上最初有 capacity 个空座位。车 只能 向一个方向行驶(也就是说,不允许掉头或改变方向) 给定整数 capacity 和一个数组…...
项目开发维护技术文档(总结梳理)
目录 一、项目背景 二、架构设计 1.技术栈 2.架构图 3.代码结构 三、模块划分 1.用户模块 2.商品模块 四、开发规范 1.命名规范 2.代码格式 3.版本控制 五、部署流程 1.环境要求 2.部署流程 六、问题解决 1.数据库连接异常 2.Redis缓存失效 七、参考资料 项…...
01_学习使用javax_ws_rs_上传文件
文章目录 1 前言2 Maven 依赖3 上传接口4 如何解析 MultipartFormDataInput5 结语 1 前言 使用 Spring MVC 来处理文件上传,想必是大家耳熟能详的了,如下代码: ResponseBody PostMapping("/upload") public String upload(Request…...
MFC 发布CLXHHandleEngine动态库1.0.0.0版本
第一版发布以下功能,此项目使用VS2013创建,项目配置包括Unicode的Mdd,md与多字节版本: //MFC Grid表格 #include "../MFCGridCtrl/GridCtrl.h" //使用AES与Base64加密解密可以与java中的AES加解密衔接 //AES加密解密 #include &q…...
MicroPython 基于microdot框架搭建网页服务器
MicroPython 基于microdot框架搭建网页服务器 简介简单demo 简介 Microdot是一个极简的Python web框架,灵感来自于Flask,它被设计用来运行在资源有限的系统上,如微控制器。它运行在标准的Python和MicroPython上。 API参考microdot 资源下载m…...
FL Studio21.2汉化永久中文语言包
FL Studio21.2这款软件在国内被广泛使用,因此又被称为"水果"。它提供音符编辑器,可以针对作曲者的要求编辑出不同音律的节奏,例如鼓、镲、锣、钢琴、笛、大提琴、筝、扬琴等等任何乐器的节奏律动。此外,它还提供了方便快…...
Glide结合OkHttp保证短信验证接口携带图形验证码接口返回Cookie值去做网络请求
一、实现效果 二、步骤 注意:仅展示核心部分代码 1、导入依赖 api com.github.bumptech.glide:glide:4.10.0 kapt com.github.bumptech.glide:compiler:4.10.0 api com.squareup.okhttp3:okhttp:3.11.0 api com.squareup.okhttp3:logging-interceptor:3.11.02、自…...
怎样用Ajax提交from表单并接收其中的json数据
怎样用Ajax提交表单并接收其中的json数据 需求:实现点击按钮后,数据以表单形式提交至服务器,并接收来自服务器的返回数据。过程中页面不刷新。 AJAX 不是新的编程语言,而是一种使用现有标准的新方法。AJAX 是与服务器交换数据并…...
【动态规划】LeetCode-746LCR 088.使用最小花费爬楼梯
🎈算法那些事专栏说明:这是一个记录刷题日常的专栏,每个文章标题前都会写明这道题使用的算法。专栏每日计划至少更新1道题目,在这立下Flag🚩 🏠个人主页:Jammingpro 📕专栏链接&…...
Unity 接入TapADN播放广告时闪退 LZ4JavaSafeCompressor
通过跟踪安卓日志,发现报如下错误 Didnt find class "com.tapadn.lz4.LZ4JavaSafeCompressor" 解决方案: 去掉Minify这边的勾选,再打包即可。...
【九】linux下部署frp客户端服务端实践(内网穿透)
linux下部署frp客户端服务端实践 简介: 今天有一个这样的需求,部署在公司内部局域网虚拟机上的服务需要在外网能够访问到,这不就是内网穿透的需求吗,之前通过路由器实现过,现在公司这块路由器不具备这个功能了&#x…...
华为1+x网络系统建设与运维(中级)-练习题2
一.设备命令 LSW1 [Huawei]sys LSW1 同理可得,给所有设备改名 二.VLAN LSW1 [LSW1]vlan ba 10 20 [LSW1]int g0/0/1 [LSW1-GigabitEthernet0/0/1]port link-type trunk [LSW1-GigabitEthernet0/0/1]port trunk allow-pass vlan 10 20 [LSW1-GigabitEthernet0/0/1]in…...
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造,完美适配AGV和无人叉车。同时,集成以太网与语音合成技术,为各类高级系统(如MES、调度系统、库位管理、立库等)提供高效便捷的语音交互体验。 L…...
DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径
目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...
基于Uniapp开发HarmonyOS 5.0旅游应用技术实践
一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架,支持"一次开发,多端部署",可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务,为旅游应用带来…...
【AI学习】三、AI算法中的向量
在人工智能(AI)算法中,向量(Vector)是一种将现实世界中的数据(如图像、文本、音频等)转化为计算机可处理的数值型特征表示的工具。它是连接人类认知(如语义、视觉特征)与…...
C++.OpenGL (10/64)基础光照(Basic Lighting)
基础光照(Basic Lighting) 冯氏光照模型(Phong Lighting Model) #mermaid-svg-GLdskXwWINxNGHso {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-GLdskXwWINxNGHso .error-icon{fill:#552222;}#mermaid-svg-GLd…...
大学生职业发展与就业创业指导教学评价
这里是引用 作为软工2203/2204班的学生,我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要,而您认真负责的教学态度,让课程的每一部分都充满了实用价值。 尤其让我…...
Java多线程实现之Thread类深度解析
Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...
基于Springboot+Vue的办公管理系统
角色: 管理员、员工 技术: 后端: SpringBoot, Vue2, MySQL, Mybatis-Plus 前端: Vue2, Element-UI, Axios, Echarts, Vue-Router 核心功能: 该办公管理系统是一个综合性的企业内部管理平台,旨在提升企业运营效率和员工管理水…...
(一)单例模式
一、前言 单例模式属于六大创建型模式,即在软件设计过程中,主要关注创建对象的结果,并不关心创建对象的过程及细节。创建型设计模式将类对象的实例化过程进行抽象化接口设计,从而隐藏了类对象的实例是如何被创建的,封装了软件系统使用的具体对象类型。 六大创建型模式包括…...
WebRTC从入门到实践 - 零基础教程
WebRTC从入门到实践 - 零基础教程 目录 WebRTC简介 基础概念 工作原理 开发环境搭建 基础实践 三个实战案例 常见问题解答 1. WebRTC简介 1.1 什么是WebRTC? WebRTC(Web Real-Time Communication)是一个支持网页浏览器进行实时语音…...
