ubuntu:gcc编译器使用
gcc 编译流程
- 预处理
- 编译
- 汇编
- 链接
1、预处理阶段
该阶段对包含的头文件、宏定义进行处理。
hello.c如下
#include <stdio.h>
int main()
{
printf("Hello World");
}
输入以下命令对hello.c进行预处理
sudo gcc -E hello.c -o hello.i
以.i
为后缀的文件为经过预处理的C原始程序,上述命令的-E
选项是对c文件只进行预处理不编译,-o选项指目标文件。
hello.i文件内容如下所示,可见gcc已经对hello.c进行了预处理,把“stdio.h”的内容插入到了hello.i文件中
2、编译阶段
此阶段gcc检查代码是否有错误,检查无误后将代码翻译成汇编代码
输入以下命令对预处理得到的.i
文件进行编译,生成.s
文件
sudo gcc -S hello.i -o hello.s
-S选项是只编译,不进行汇编,生成的汇编代码如下图所示
3、汇编阶段
该阶段把编译阶段生成的.s
文件转成目标文件。
输入以下命令将.s
文件转化为.o
结尾的二进制目标代码
sudo gcc -c hello.s -o hello.o
-c为只汇编不链接
4、链接阶段
此阶段将hello.c 需要使用的printf
函数链接到函数库中(/lib/x86_64-linux-gnu/libc.so.6),因为函数库实现了printf
函数,而“stdio.h”中只有函数声明,只有链接到函数库libc.so.6
中才能调用printf
函数。
函数库分为:静态库和动态库。
静态库(后缀通常为.a
)是指在编译链接时,将库文件代码全部加入可执行文件中,因此生成的文件大,但是运行时不需要库文件了。
动态库(后缀通常为.so
)是在程序执行时加载,可以节省系统开销。
输入以下命令完成对hello.o
文件的链接,并生成可执行文件
sudo gcc hello.o -o hello
输入./hello
运行该可执行文件,结果如下
代码里面忘记加回车了,影响不大 😂
gcc常用选项
-o file
输出文件名为file的文件-v
打印编译过程等信息-I dir
头文件搜索目录添加dir目录
制作函数库
先准备两个c文件:usgn_pow.c、pow_test.c如下所示
/*usgn_pow.c:库程序*/
unsigned long long unsgn_pow(unsigned int x, unsigned int y)
{
unsigned long long res = 1;
if (y == 0)
{
res = 1;
}
else if (y == 1)
{
res = x;
}
else
{
res = x * unsgn_pow(x, y - 1);
}
return res;
}
/*pow_test.c*/
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
unsigned int x, y;
unsigned long long res;
if ((argc < 3)||(sscanf(argv[1],"%u", &x) != 1)||(sscanf(argv[2], "%u", &y)) != 1)
{
printf("Usage: pow base exponent\n");
exit(1);
}
res = unsgn_pow(x,y);
printf("%u ^ %u = %u\n", x, y, res);
exit(0);
}
1、静态库的创建和使用
输入以下命令,使用ar
归档工具将目标文件集成在一起。
sudo gcc -c unsgn_pow.c
ar rcsv libpow.a unsgn_pow.o
输出如下:
在目录下生成了一个libpow.a
静态库文件:
完成上述步骤后,使用下面的命令编译主程序,并链接到刚刚生成的静态库libpow.a
:
sudo gcc pow_test.c -o pow_test -L . -lpow
其中 选项 “-L dir”是在库文件搜索路径中添加dir目录,“-lname”选项指示编译时链接到库文件libpow.a
或libpow.so
。
输入./pow_test 2 2
命令后运行结果如下所示:
2、动态库的创建和使用
首先使用gcc的-fPIC
选项为动态库构造一个目标文件(.o后缀)
sudo gcc -fPIC -Wall -c unsgn_pow.c
再使用-shared
选项生成一个动态库libpow.so
sudo gcc -shared -o libpow.so unsgn_pow.o
最后编译程序并链接动态库libpow.so
。
注意这时候目录下同时存在静态库和动态库,如图:
输入以下命令:
sudo gcc -o pow_test pow_test.c -L . -lpow
这个命令和之前链接静态库是一样的,那么这次链接的是动态库还是静态库呢?答案是:动态库。
链接动态库还是链接静态库可以用 -static
选项和-shared
选项指定,-static
选项是链接静态库,禁止使用动态库;-shared
选项是默认选项,尽可能的链接动态库,当没有动态库时才链接静态库。
执行可执行程序之前需要注册动态库路径名这里 直接将libpow.so
文件复制到/lib
或者/usr/lib
目录下,这是系统的默认库路径:
sudo cp libpow.so /lib
sudo cp libpow.so /lib
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从二进制到误差:逐行拆解C语言浮点运算中的4008175468544之谜
· .NET制作智能桌面机器人:结合BotSharp智能体框架开发语音交互
· 软件产品开发中常见的10个问题及处理方法
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
· C# 13 中的新增功能实操
· 万字长文详解Text-to-SQL
· Ollama本地部署大模型总结
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(4)
· 卧槽!C 语言宏定义原来可以玩出这些花样?高手必看!