Ubuntu18.04下C语言程序的编译原理

我们通常把一些公用函数制作成函数库,供其它程序使用。函数库分为静态库和动态库两种。静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库。动态库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入,因此在程序运行时还需要动态库存在。
本文主要通过举例来说明在 Linux 中如何创建静态库和动态库,以及使用它们。

一、用gcc生成静态库和动态库

(1)生成x2x.c、x2y.c、main1.c C语言文件

x2x.h

#ifndef __x2x_H
#define __x2x_H

#include<stdio.h>

float x2x(int a,int b);

#endif

x2x.c(两个数相乘)

#include "x2x.h"

float x2x(int a,int b)
{
        return a*b;
}

x2y.h

#ifndef __x2y_H
#define __x2y_H

#include<stdio.h>

float x2y(int a1,int b1);

#endif

x2y.c(两个数相加)

#include "x2y.h"

float x2y(int a1,int b1)
{
        return a1+b1;
}

main1.c

#include"x2x.h"
#include"x2y.h"

int main()
{
        int x=2,y=9;
        printf("%.2f\n",x2x(x,y));
        printf("%.2f\n",x2y(x,y));
        return 0;
}

(2)使用gcc分别将.c文件编译为3个.o 目标文件

无论静态库,还是动态库,都是由.o文件创建的。因此,我们必须将程序通过gcc先编译成.o 文件。

1、使用gcc命令

gcc -c x2x.c x2y.c main1.c

2、输入ls查看结果
![在这里插入图片描述](https://img-blog.csdnimg.cn/20201013204217880.png#pic_center

可以看到已经生成了相关的.o文件。

(3)由.o文件生成静态库

静态库文件名的命名规范是以 lib 为前缀,紧接着跟静态库名。
1、输入gcc命令

ar crv libtest.a x2x.o x2y.o

2、使用ls查看运行结果
在这里插入图片描述

(4) 在程序中使用静态库

静态库制作完了,如何使用它内部的函数呢?只需要在使用到这些公用函数的源程序中包 含这些公用函数的原型声明,然后在用gcc命令生成目标文件时指明静态库名,gcc将会从 静态库中将公用函数连接到目标文件中。注意,gcc 会在静态库名前加上前缀 lib,然后追加扩展名.a 得到的静态库文件名来查找静态库文件。

1、输入gcc命令

gcc main1.c libtest.a -o main1

运行main1查看结果

./main1

运行结果:
在这里插入图片描述
查看main1大小:
在这里插入图片描述

(5)由.o 文件创建动态库文件

动态库文件名命名规范和静态库文件名命名规范类似,也是在动态库名增加前缀 lib,但其文件扩展名为.so。

1、输入gcc命令

gcc -shared -fPIC -o libtest.so main1.o

ls命令运行结果:
在这里插入图片描述

(6)在程序中使用动态库

1、输入gcc命令

gcc main1.c libtest.so -o main1
./main1

运行结果:
在这里插入图片描述
我们可以看到有错误提示:找不到动态库文件libtest.so。这是因为程序在运行时,会在 /usr/lib 和 /lib 等目录中查找需要的动态库文件。若找到,则载入动态库,否则将提
示类似上述错误而终止程序运行。
解决方法:我们将文件 libtest.so 复制到目录 /usr/lib 中。

sudo mv libtest.so /usr/lib
./main1

运行结果:
在这里插入图片描述

(7)静态库与动态库比较

静态库文件的大小:
在这里插入图片描述

使用静态库生成可执行文件的大小:
在这里插入图片描述
动态库文件的大小:
在这里插入图片描述

使用动态库生成可执行文件的大小:
在这里插入图片描述
可以看到静态库文件要比动态库文件要小。

二、as汇编编译器

(1)下载安装nasm

1、输入gcc命令

sudo apt-get install nasm

运行结果:
在这里插入图片描述

(2)对示例代码“hello.asm”编译生成可执行程序

1、创建“hello.asm”文件

vim hello.asm

hello.asm代码:

; hello.asm 
section .data            ; 数据段声明
        msg db "Hello, world!", 0xA     ; 要输出的字符串
        len equ $ - msg                 ; 字串长度
section .text            ; 代码段声明
global _start            ; 指定入口函数
_start:                  ; 在屏幕上显示一个字符串
        mov edx, len     ; 参数三:字符串长度
        mov ecx, msg     ; 参数二:要显示的字符串
        mov ebx, 1       ; 参数一:文件描述符(stdout) 
        mov eax, 4       ; 系统调用号(sys_write) 
        int 0x80         ; 调用内核功能
                         ; 退出程序
        mov ebx, 0       ; 参数一:退出代码
        mov eax, 1       ; 系统调用号(sys_exit) 
        int 0x80         ; 调用内核功能

2、生成可执行文件

编译:

nasm -f elf64 hello.asm

链接:

ld -s -o hello hello.o

运行:

./hello

运行结果:
在这里插入图片描述

大小:
在这里插入图片描述

(3)用C语言编译生成程序

1、创建"hello1.c"

vim hello1.c

hello1.c

#include<stdio.h>

int main(void)
{
        printf("Hello World!\n");
        return 0;
}

编译且运行:

gcc hello1.c -o hello1
./hello1

运行结果:
在这里插入图片描述

C语言编译生成的可执行文件大小:
在这里插入图片描述
nasm编译生成可执行文件大小:
在这里插入图片描述

可以看到,C语言编译生成的可执行文件要比nasm要大。

三、Linux中的第三方库函数

(1)最常用的光标(curses)的主要函数功能

1、 游标的控制:

move(y,x): 将游标移动至 x,y 的位置. 
getyx(win,y,x): 得到目前游标的位置. (请注意! 是 y,x 而不是&y,&x)

2、 有关清除屏幕:

clear() and erase(): 将整个萤幕清除. (请注意配合refresh() 使用)

3、 如何在屏幕上显示字元:

echochar(ch): 显示某个字元.
addch(ch): 显示某个字元. 
mvaddch(y,x,ch): 在(x,y)上显示某个字元. 相当于呼叫move(y,x);
addch(ch); addstr(str): 显示一串字串.
mvaddstr(y,x,str): 在(x,y) 上显示一串字串. 相当於呼叫move(y,x);addstr(str);
printw(format,str): 类似 printf() , 以一定的格式输出至屏幕.
mvprintw(y,x,format,str): 在(x,y) 位置上做 printw 的工作,相当於呼叫move(y,x);printw(format,str);

4、如何从键盘上读取字元:

getch(): 从键盘读取一个字元. (注意! 传回的是整数值) 
getstr(): 从键盘读取一串字元.
scanw(format,&arg1,&arg2...): 如同 scanf, 从键盘读取一串字元.

(2)以游客身份体验一下即将绝迹的远古时代的 BBS

在 win10 系统中,“控制面板”–>“程序”—>“启用或关闭Windows功能”,启用 “telnet client"和"适用于Linux的Windows子系统”(后面会使用)。 然后打开一个cmd命令行窗口,命令行输入 telnet bbs.newsmth.net

在这里插入图片描述

(3) 查看头文件与库文件

1、输入gcc命令:

 sudo apt-get install libncurses5-dev

2、查看头文件

cd /usr/include
ls

在这里插入图片描述
3、查看库文件

cd /usr/lib
ls

在这里插入图片描述

(4)Linux 环境下C语言编译实现贪吃蛇游戏

代码:http://www.linuxidc.com/Linux/2011-08/41375.htm贪吃蛇代码

四、总结

本篇文章主要总结了如何用gcc生成静态库与动态库,并生成可执行文件,比较了动态库与静态库的大小;了解了as汇编编译器以及第三方库函数curses函数。

五、参考资料

贪吃蛇代码:http://www.linuxidc.com/Linux/2011-08/41375.htm
curses函数:https://blog.csdn.net/byxdaz/article/details/1780449

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值