c语言编译的4个阶段:
预处理、 编译、 汇编、 链接
预处理阶段会在源代码中查找预编译指令,其中主要是头文件展开(include),宏定义(defind),选择性编译(ifdef)三种指令
预处理命令以符号 # 开头
优势:
1 扩展了c程序设计的环境
2 简化了程序开发过程
3 提高程序的可读性
注意:
1 实际上不是c语言的一部分【只是一点小技巧】
2 预编译指令在编译前由预处理程序对源文件的预处理文件进行加工。
1 include
作用:
# 引入头文件
在预编译编译阶段会将该行代码 替换 为引入的头文件中的代码
语法:
语法1:
#include <要引入的头文件> 引入的是系统提供的头文件
语法2:
#include “要引入的头文件” 先在当前目录下寻找,如果没有再去系统提供头文件目录下寻找。
注意:
1
include 经常用来包含头文件,可以包含源文件,但是大家不要包含源文件
头文件中也可以定义函数,但是不建议 定义函数
2
预编译只会对 include 等预处理操作进行处理并不会进行语法检查,下一阶段的 编译才会 检查语法对错
2 define
作用: 定义一个常量或者定义一段代码
分类:
- 不带参宏
- 带参宏
不带参宏:
静态宏定义
【一般用静态宏定义】
步骤:
1 宏定义:
静态定义
#define 宏名称 值
注意: 值可以可无
2 使用宏
宏名称
3 取消宏【一般没人取消所以不理会】
undef 宏名称
注意: 一旦取消,该宏就不能使用
使用范围:
宏定义开始到取消宏
动态宏定义
【搞事7用动态宏定义】
带参宏
步骤: 1,宏定义 #define宏名称(形参列表)代码; 2,使用宏 宏名称(实参列表); 3,取消宏 #undef 宏名称 带参宏与带参函数的区别 带参宏被调用多少次就会展开多少次,执行代码的时候没有函数调用的过程,不需要压栈弹栈。所以带参宏是浪费了空间,因为被展开多次,节省时间。 带参函数,代码只有一份,存在代码段,调用的时候去代码段取指令,调用的时候要,压栈弹栈。有个调用的过程,所以说,带参函数是浪费了时间,节省了空间。 带参函数的形参是有类型的,带参宏的形参没有类型名。
3 选择性编译
作用:选择性的对代码进行编译
头文件模板:
#ifndef 自定义宏 #define 自定义宏 引入头文件 声明变量 声明函数 #endif
比如这样:
其他的正常就使用
注意:
- 此时需要在该头文件对应的源文件中引入该头文件
- 在使用该源文件中函数的源文件中再引入该头文件,此时不会重复声明
动态库与静态库
-
动态编译使用动态库 生成的可执行程序小,对库的依赖大
举例: 一般下载的软件后还需要进行更新 根本就是对依赖库的检查更新
-
静态编译使用静态库 生成的可执行程序大,对库的依赖小
-
当静态与动态库名重名 但是因为后缀不一样 所以使用命令不同的时候 就会调用不同的库产生不同的库文件本应该产生的效果
程序编译
分类:
静态编译
```markdown > gcc -static 源文件 -o 生成的可执行程序名 ```
动态编译
gcc 源文件名 -o 生成的可执行程序名
哪怕程序一样但是选择的不同方式进行编译结果不一样
第三方库 也就是就包含了 头文件和库文件
动态库:.so
【制作的时候有可能有一个bug 使用的时候需要注意有三个可能出现的bug】
制作:
gcc -shared 源文件名 -o lib生成的动态库名.so 举例: gcc -shared arr_utils.c -o libutils.so # 注意 起名对生成的动态库名 必须以 lib开头 结尾是.so 中间部分自己改
注意:
gcc -shared -fPIC 源文件名 -o lib生成的动态库名.so
使用:
情况一:
# 使用动态库的源文件与动态库在同一文件夹下 gcc 源文件名 1ib动态库名.so -o 可执行文件名
注意:
如果在执行可执行程序时出现一下问题需要加入
这是为当前命令窗口添加环境后再去执行程序v
export LD_LIBRARY_PATH=./:$LD_LIBRARY_PATH // 单独起一行
情况二:【常出的问题】
之前是将头文件 源文件和库文件都在同一目录下 所以直接用
但是分文件后就得告知从哪去拿头 从那去拿库文件等…
# 使用动态库的源文件与动态库不在同一文件夹下
使用动态库的源文件与动态库不在同一文件夹下
gcc 源文件名 -o lib动态库名.so -L库文件路径 -l库名 -I头文件所在路径
【注意】:
-L 是指定库文件的路径 -l 指定找哪个库,指定的只要库文件名1ib后面.so前面的部分 -I 指定头文件的路径
如果出现一下问题,需要加入 export LD_LIBRARY_PATH=库文件所在路径:$SLD_LIBRARY_PATH
情况三:
【不常用 因为担心库文件名和系统提供的库文件名 重名】
动态库文件在系统提供的文件夹
系统提供的文件夹 /usr/lib 系统提供存储动态库的文件夹 /usr/include 系统提供存储头文件的文件夹
gcc 源文件名 -l库文件名 -o 生成的可执行文件夹
静态库:.a
制作:
1 将要编译为库文件的的源编译为二进制文件 gcc -c 源文件名 -o 二进制文件名.o 2 将二进制文件转换为静态库文件 ar rc lib库文件名.a 二进制文件名.o
使用:
情况一:
使用静态库的源文件与动态库在同一文件夹下
gcc -static 源文件名 1ib动态库名.a -o 可执行文件名
情况二:
使用静态库的源文件与动态库不在同一文件夹下
gcc -static 源文件名 -o 生成的可执行文件名 -L库文件路径 -1库名 -I头文件所在路径
情况三:
静态库文件在系统提供的文件夹
/usr/lib 系统提供存储动态库的文件夹 /usr/include 系统提供存储头文件的文件夹
gcc -static 源文件名 -l 库文件名 -o 生成的可执行文件夹
件名
情况二:
使用静态库的源文件与动态库不在同一文件夹下
gcc -static 源文件名 -o 生成的可执行文件名 -L库文件路径 -1库名 -I头文件所在路径
情况三:
静态库文件在系统提供的文件夹
/usr/lib 系统提供存储动态库的文件夹 /usr/include 系统提供存储头文件的文件夹
gcc -static 源文件名 -l 库文件名 -o 生成的可执行文件夹