目录
C语言函数库提供了一系列预定义、方便重复使用的函数,通过使用这些函数,程序员可以快速完成各种常见的编程任务,而无需从头编写这些功能,从而大大提高了编程效率。
函数库包括静态链接库(LIB)和动态链接库(DLL)。两者的主要区别:
一、库函数的概念
C语言函数库提供了一系列预定义、方便重复使用的函数,通过使用这些函数,程序员可以快速完成各种常见的编程任务,而无需从头编写这些功能,从而大大提高了编程效率。
函数库包括静态链接库(LIB)和动态链接库(DLL)。两者的主要区别:
- 静态库:在编译时将库文件的代码全部加入到可执行文件中,因此生成的文件比较大,但在运行时不再需要库文件。静态库的后缀名一般为 .a,例如 libxxx.a。
- 动态库:在编译时并没有被编译进目标代码中,而是在程序运行时才被载入。动态库的后缀名通常为 .so(在Linux下)或 .dll(在Windows下),例如 libxxx.so 或 libxxx.dll。
- 静态库:适合于需要独立运行、变更慢的程序,或者在没有网络连接的环境中使用,因为静态库的程序不需要外部库的支持。
- 动态库:适合于软件功能需要频繁更新的场景,因为动态库的更新不需要重新编译程序,只需更新动态库即可。此外,多个程序可以共享同一个动态库,节省磁盘和内存空间。
使用库函数的好处主要包括以下几个方面:
- 提高开发效率:库函数封装了许多常用的操作和算法,开发者可以直接调用这些函数,无需从头开始编写复杂的代码,从而节省了开发时间和工作量。
- 提高代码可维护性:使用库函数可以使代码更加模块化,结构更清晰,便于维护和调试。库函数通常遵循一定的标准接口规范,使得不同的开发者可以在相同的环境下使用相同的函数来完成相同的任务,提高了代码的可读性和可维护性。
- 安全性和保护产权:调用库函数通常比直接操作底层系统调用更安全,因为库函数会处理一些底层细节,减少了直接操作底层资源的风险,编译的二进制文件,非源码发布功能软件可以保护自己的产权。
二、在Windows系统中库的加载路径
- 标准路径:在Windows系统中,C标准库通常位于编译器的安装目录中。例如,对于Visual Studio,标准库文件通常位于C:\Program Files (x86)\Microsoft Visual Studio\<version>\VC\Tools\MSVC\<version>\lib目录中。如:MINGW64的在……\mingw64\lib目录中。
- 环境变量:编译器和链接器会查找环境变量LIB和INCLUDE指定的目录。LIB环境变量用于指定额外的库文件目录,而INCLUDE环境变量用于指定头文件目录。
PATH:虽然主要用于指定可执行文件的查找路径,但在某些情况下也可以间接影响动态库的加载。通过调整PATH环境变量,可以改变系统查找可执行文件的顺序,从而影响动态库的加载路径。
- 项目配置:在Visual Studio等IDE中,可以通过项目属性设置来指定库文件和头文件的相对路径或绝对路径。
三、基于MINGW64创建自己的静态函数库
MINGW64 的全称是 Minimalist GNU for Windows 64-bit,其主要目标是提供一个最小化的、可以运行 GNU 工具链的 Windows 环境。它包括了许多常见的 GNU 工具和库,如 GCC(GNU Compiler Collection,GNU 编译器集合)、GDB(GNU Debugger,GNU 调试器)等,以及一个 Windows 兼容的 POSIX API 实现。这些工具允许开发者在 Windows 上编写、编译和调试 C/C++ 等编程语言的代码,同时也能运行许多在 Unix 系统上编写的脚本和工具。
1.编辑源文件.cpp和头文件.h
为了展示库的创建过程,随意写了两个函数,printHello函数,功能输出字符串;sum函数,功能求整型 可变参数 的和,即求和函数 提供任意个指定个数整数的求和。
#include <stdarg.h>
#include <iostream>
namespace MyLibrary {//使用命名空间将函数放在一个命名空间中,以避免命名冲突
void printHello(char *sp) {
std::cout << "Hello, World!with lib fuction" <<sp<< std::endl;
}
void sum(int a, ...) {
va_list myargs;
va_start(myargs, a);
int i;
float total=0;
for (i = 0; i < (int)a; i++) {
total += va_arg(myargs, int); // 获取下一个 int 类型的参数
}
// 清理 args
va_end(myargs);
std::cout << "Hello, World! sum with lib fuction" <<a<<total<< std::endl;
}
}
头文件是源文件里函数的声明,自行创建。
2. 编译源文件、生成函数库
使用g++编译器创建静态库,将以上代码编译成静态库(.a)。
g++编译器创建静态库的指令,在CMD中输入命令,分两步:
①g++ -c mylibrary.cpp -o mylibrary.o ,得到目标文件
②ar rcs libmylibrary.a mylibrary.o ,得到库文件。
得到libmylibrary.a和mylibrary.o文件,在资源管理器可以看到下结果:
3、测试自建库是否成功
注意:使用C语言函数库时,通常需要包含相应的头文件
如果头文件和库文件不在上述搜索位置存放,则在编译器编译时需要指定对应依赖的头文件和库文件的位置,否则编译器找不到库文件。编译指令后加可选配置参数,指定方式和含义如下:
使用-I(大写的i)指定头文件位置
使用-L指定库文件位置
使用 -l库名 指定链接的库名
同样在CMD中输入:g++ test.cpp -L. -lmylibrary -o mytest,表示使用当前路径下的库mylibrary,编译test.cpp 链接生成mytest.exe,提醒 其中配置参数是否带路径,自己可以根据需要添加。
#include<stdio.h>
#include <iostream>
#include <stdarg.h>
#include "lib1.h"
int main() {
MyLibrary::printHello(" @@@test good");
MyLibrary::sum(3,10,6,10);
getchar();
return 0;
}
测试程序的编译指令、编译结果、执行结果如下图:
非常感谢你每一次的停留和阅读!这承载了满满厚爱与支持!愿你在编程的道路上日新月异,收获满满的成就和喜悦!