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库和ttty
endwin() 关闭curses并重置tty
move(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 运行该程序