GCC编译器背后的故事
发布日期:2021-11-03 09:33:17
浏览次数:2
分类:技术文章
本文共 2527 字,大约阅读时间需要 8 分钟。
GCC编译器背后的故事
一、可执行程序是如何被组装的
1、用 gcc 生成 .a 静态库和 .so动态库
第 1 步:编辑生成例子程序 hello.h、hello.c 和 main.c。
先创建一个作业目录,保存本次练习的文件。 然后用 vim、nano 或 gedit 等文本编辑器编辑生成所需要的 3 个文件。 hello.c是函数库的源程序,其中包含公用函数 hello,该函数将在屏幕上输出"Hello XXX!"。hello.h(见程序 1)为该函数库的头文件。main.c为测试库文件的主程序, 在主程序中调用了公用函数 hello。程序 1: hello.h
程序 2: hello.c 程序 3: main.c第 2 步:将 hello.c 编译成.o 文件。
无论静态库,还是动态库,都是由.o 文件创建的。因此,我们必须将源程序 hello.c 通过 g cc 先编译成.o 文件。在系统提示符下键入以下命令得到 hello.o 文件。之后输出ls查看是否生成.o文件。 第 3 步:由.o 文件创建静态库 静态库文件名的命名规范是以 lib 为前缀,紧接着跟静态库名,扩展名为.a。例如:我们将 创建的静态库名为 myhello,则静态库文件名就是 libmyhello.a。在创建和使用静态库时, 需要注意这点。创建静态库用 ar 命令。在系统提示符下键入以下命令将创建静态库文件 libmyhello.a。同时输入ls产看是否生成.a文件 第 4 步:在程序中使用静态库 输入gcc main.c libmyhello.a -o hello 输入./hello查看结果 删除静态库文件试试公用函数 hello 是否真的连接到目标文件 hello 中了。 程序照常运行,静态库中的公用函数已经连接到目标文件中了。第 5 步:由.o 文件创建动态库文件
动态库文件名命名规范和静态库文件名命名规范类似,也是在动态库名增加前缀 lib,但其 文件扩展名为.so。例如:我们将创建的动态库名为 myhello,则动态库文件名就是 libmyh ello.so。用 gcc 来创建动态库。 在系统提示符下键入以下命令得到动态库文件 libmyhello.so。 输入ls查看是否生成.so文件 第 6 步:在程序中使用动态库 输入gcc main.c libmyhello.so -o hello 输入./hello查看结果 错误提示,找不到动态库文件 libmyhello.so。程序在运行时,会在/usr/lib 和/lib 等目录中查找需要的动态库文件。若找到,则载入动态库,否则将提示类似上述错误而终止程序运行。我们将文件 libmyhello.so 复制到目录/usr/lib 中。 移动文件后再次输入./hello查看结果。 成功了。这也进一步说明了动态库在程序运行时是需要的。2、动态库和静态库生成可执行文件大小的对比
第 1 步:编辑生成程序 A.h、A.c、B.h、B.c、main.c
创建一个 test2文件夹,并在该文件夹中分别创建子程序 A.h、A.c、B.h、B.c、main.c 程序1 A.h 程序2 A.c 程序3 B.h 程序4 B.c 程序5 main.c 第二步:用静态库文件进行链接,生成可执行文件 将 A.c,B.c 编译成 .o文件 用.o文件创建静态库在程序中使用静态库
第三步:用动态库文件进行链接,生成可执行文件 用.o文件创建动态库 在程序中使用动态库 两个可执行文件大小的比较 按上面的方法由静态库链接生成的可执行文件,不是完全由静态库链接生成的,因为在 main.c 中调用的 stdio.h 是由动态链接的,所以需要重新由静态库链接生成一个可执行文件,否则可能将会出现静态库生成的可执行文件小于动态库生成的。size:用于查看文件大小
ldd:查看链接了那些动态库二、gcc编译器的编译
1、创建一个 test0 文件夹,并在该文件夹中创建一个 hello.c 程序
hello.c文件内容 2、程序的编译过程 预编译(将源文件 hello.c 文件预处理生成 hello.i) 编译(将预处理生成的 hello.i 文件编译生成汇编程序 hello.s) 汇编(将编译生成的 hello.s 文件汇编生成目标文件 hello.o) 链接(分为静态链接和动态链接,生成可执行文件)4、在ubuntu中下载安装nasm,对示例汇编代码“hello.asm”编译生成可执行程序,并与上述用C代码的编译生成的可执行程序大小进行对比。
编译汇编 hello.asm文件,并于C代码的编译生成的程序大小进行对比
编译(elf 默认为32位)并链接:
汇编与C代码的编译生成的可执行程序大小对比三、了解实际程序是如何借助第三方库函数完成代码设计
光标库(curses)的主要函数功能
nitscr() 初始化curses库和tttyendwin() 关闭curses并重置ttymove(y,x) 将光标移动至x,y的位置getyx(win,y,x) 得到目标游标的位置clear()and erase() 将整个屏幕清楚
echochar(ch) 显示某个字元
1、体验一下即将绝迹的远古时代的 BBS
在 win10 系统中,“控制面板”–>“程序”—>“启用或关闭Windows功能”,启用 “telnet client” 和"适用于Linux的Windows子系统"(后面会使用)。 然后打开一个cmd命令行窗口,命令行输入 telnet bbs.newsmth.net,以游客身份体验一下即将绝迹的远古时代的 BBS (一个用键盘光标控制的终端程序)。
2、Linux 环境下C语言编译实现贪吃蛇游戏
安装curses库
通过 whereis 命令头文件和库文件被安装的目录 编译实现贪吃蛇游戏 代码参考(http://www.linuxidc.com/Linux/2011-08/41375.htm)./mysnake 运行该程序
转载地址:https://blog.csdn.net/weixin_51118019/article/details/109102956 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
初次前来,多多关照!
[***.217.46.12]2024年04月10日 09时43分56秒
关于作者
喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
【Leetcode刷题篇/面试篇】经典动态规划-买卖股票问题总结汇总
2019-04-26
【Java锁体系】五、隐式锁和显式锁的区别(Synchronized和Lock的区别)
2019-04-26
【Java锁体系】七、JMM内存模型详解
2019-04-26
【Java锁体系】八、MESI缓存一致性协议讲解
2019-04-26
【面试篇】Java锁体系
2019-04-26
【面试篇】JVM体系
2019-04-26
【Leetcode刷题篇】leetcode406 根据身高重建队列
2019-04-26
【Leetcode刷题篇】leetcode581 最短无序连续子数组
2019-04-26
【Leetcode刷题篇】leetcode538 把二叉搜索树转换为累加树
2021-06-29
【多线程与高并发】线程的优先级是怎么回事?
2021-06-29
【多线程与高并发】Java守护线程是什么?什么是Java的守护线程?
2021-06-29
【Leetcode刷题篇/面试篇】-前缀树(Trie)
2021-06-29
【Leetcode刷题篇】leetcode337 打家劫舍III
2021-06-29
【Leetcode刷题篇】leetcode4 寻找两个正序数组的中位数
2021-06-29
【Leetcode刷题篇】leetcode316 去除重复字母
2021-06-29
【Leetcode刷题篇】leetcode1081 不同字符的最小子序列
2021-06-29
【面试篇】Java网络编程与IO流体系
2021-06-29
【大话Mysql面试】-Mysql的索引为什么要使用B+树,而不是B树,红黑树等之类?
2021-06-29
【大话Mysql面试】-如何通俗易懂的了解Mysql的索引最左前缀匹配原则
2021-06-29