gcc编译器的使用操作

一、gcc 生成 .a 静态库和 .so 动态库

1.创建作业目录

(1)创建test1目录
在这里插入图片描述
(2)进入test1目录
在这里插入图片描述

2.用vim编写hello.h、hello.c和main.c文件

程序1 hello.h

#ifndef HELLO_H
#define HELLO_H
void hello(const char *name);
#endif //HELLO_H

程序2 hello.c

#include <stdio.h>
void hello(const char *name)
{
    
    
 printf("Hello %s!\n", name);
}

程序3 main.c

#include "hello.h"
int main()
{
    
    
 hello("everyone");
        return 0;
}

3.将 hello.c 编译成.o 文件

在这里插入图片描述
用ls命令查看是否生成
在这里插入图片描述

4.由.o文件创建静态库

在这里插入图片描述
用ls命令查看是否生成
在这里插入图片描述

5.程序中使用静态库

下面先生成目标程序 hello,然后运行 hello 程序看看结果如何。
在这里插入图片描述
运行hello文件
在这里插入图片描述
删除静态库文件试试公用函数 hello 是否真的连接到目标文件 hello 中了
在这里插入图片描述
程序照常运行,静态库中的公用函数已经连接到目标文件中了

6.由.o 文件创建动态库文件

动态库文件名命名规范和静态库文件名命名规范类似,也是在动态库名增加前缀 lib,但其文件扩展名为.so
在这里插入图片描述

7.在程序中使用动态库

在程序中使用动态库和使用静态库完全一样,也是在使用到这些公用函数的源程序中包含 这些公用函数的原型声明,然后在用 gcc 命令生成目标文件时指明动态库名进行编译。我 们先运行 gcc 命令生成目标文件,再运行它看看结果。
在这里插入图片描述
(或 #gcc main.c libmyhello.so -o hello 不会出错(没有 libmyhello.so 的话,会出错),但是 接下来./hello 会提示出错,因为虽然连接时用的是当前目录的动态库,但是运行时,是到 /usr/lib 中找库文件的,将文件 libmyhello.so 复制到目录/usr/lib 中就 OK 了)
在这里插入图片描述
(找不到动态库文件 libmyhello.so。程序在运行时, 会在/usr/lib 和/lib 等目录中查找需要的动态库文件。若找到,则载入动态库,否则将提 示类似上述错误而终止程序运行。)

将文件 libmyhello.so 复制到目录/usr/lib 中,再运行
在这里插入图片描述

8.当静态库和动态库同名时,gcc 命令会使用哪个库文件

先删除除.c 和.h 外的所有文件,恢复成我们刚刚编辑完举例程序状态
在这里插入图片描述
再来创建静态库文件 libmyhello.a 和动态库文件 libmyhello.so。
在这里插入图片描述
(通过上述最后一条 ls 命令,可以发现静态库文件 libmyhello.a 和动态库文件 libmyhello.s o 都已经生成,并都在当前目录中。然后,我们运行 gcc 命令来使用函数库 myhello 生成目 标文件 hello,并运行程序 hello。)

gcc -o hello main.c -L. –lmyhello

(动态库和静态库同时存在时,优先使用动态库,当然,如果直接 #gcc main.c libmyhello.a -o hello 的话,就是指定为静态库了)

./hello
./hello: error while loading shared libraries: libmyhello.so: cannot
open shar ed object file: No such file or directory

从程序 hello 运行的结果中很容易知道,当静态库和动态库同名时,gcc 命令将优先使用动 态库,默认去连/usr/lib 和/lib 等目录中的动态库,将文件 libmyhello.so 复制到目录/usr/lib 中即可。

二、作业一程序基础gcc改编生成静态库和动态库并比较大小

1.用vim编写x2x.c、x2y.c、main.c、main.h。

main.h

#ifndef MAIN
#define MAIN
#include<stdio.h>
float x2x(int x,int y);
float x2y(int x,int y);
#endif

main.c

#include"main.h"
int main()
{
    
    
        int x=16,y=10;
        printf("%f\n",x2x(x,y));
        printf("%f\n",x2y(x,y));
        return 0;
}

x2x.c

#include"main.h"
float x2x(int a,int b)
{
    
    
        float  sum=a+b;
       	return sum;
}

x2y.c

#include"main.h"
float x2y(int a,int b)
{
    
    
	float  c=a-b;
       	return c;
}

2.将x2x.c和x2y.c和main.c编译成.o文件

在这里插入图片描述

3.将x2x、x2y目标文件用 ar工具生成1个 .a 静态库文件

在这里插入图片描述

4.用 gcc将 main函数的目标文件与此静态库文件进行链接,生成最终的可执行程序,并记录大小

在这里插入图片描述
输出结果
在这里插入图片描述
静态库大小
在这里插入图片描述

5.将x2x、x2y目标文件生成1个 .so 动态库文件

在这里插入图片描述

6.用 gcc将 main函数的目标文件与此动态库文件进行链接,生成最终的可执行程序,记录大小并与静态库比较

在这里插入图片描述
错误因为找不到动态库文件 libmyhello.so。程序在运行时, 会在/usr/lib 和/lib 等目录中查找需要的动态库文件。我们将文件 libmyhello.so 复制到目录/usr/lib 中,再输出。
在这里插入图片描述
动态库大小
在这里插入图片描述
比较大小
在这里插入图片描述
由此可以看出动态库文件大小要比静态库文件大小大很多。

三、下载安装nasm并用nasm编译生成程序

1.nasm下载安装

输入命令进行下载

sudo apt-get installl nasm

在这里插入图片描述

2.“hello.asm”编译生成可执行程序

1.生成文件并写下代码
在这里插入图片描述
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.编译生成程序并运行
在这里插入图片描述
3.查看程序大小
在这里插入图片描述

3.“hello world”C代码的编译生成的程序

1.创建hello.c文件
在这里插入图片描述
写下代码

#include<stdio.h>
int void main()
{
    
    
        printf("Hello World!\n");
        return 0;
}

2.编译并输出
在这里插入图片描述
3.程序大小为
在这里插入图片描述

4.2种程序大小进行比较

在这里插入图片描述
从上面可以看出nasm生成的执行程序要比c代码编译生成的程序小得多

四、借助第三方库函数完成代码设计

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

(1)cbreak():调用cbreak函数后,除了"Del"和"Ctrl"键外,接受其他所有字符输入。
(2)nl (/nonl ):输出时,换行是否作为回车字符。nl函数将换行作为回车符,而nonl函数相反。
(3)noecho()/echo():关闭/打开输入回显功能。
(4)intrflush(WINDOW *win,bool bf) win为标准输出。当bf为true时输入Break,可以加快中断的响应。但是,有可能会造成屏幕输出信息的混乱。
(5)keypad (WINDOW *win, bool bf) : win为标准输出。调用keypad函数后,将可以使用键盘上的一些特殊字符,如方向键,转化成curses.h中的特殊键。
(6)refresh():重绘屏幕显示内容。在调用initscr函数后,第一次调用refresh函数会清除屏幕显示。

2.在Ubuntu中安装curses库

1.使用下面命令安装
在这里插入图片描述在这里插入图片描述
2.查找头文件
输入命令

cd /usr/include

在这里插入图片描述
3.查找库文件
输入命令

cd /usr/lib

在这里插入图片描述

3.以游客身份体验一下即将绝迹的远古时代的 BBS

在这里插入图片描述

4.gcc编译生成一个终端游戏

代码编译

cc mysnake1.0.c -lcurses -o mysnake1.0

输出

./mysnake1.0

在这里插入图片描述

五、总结

这次的作业学会了用gcc 生成 .a 静态库和 .so 动态库,也在游戏中了解到了curses库灵活链接和使用。

参考代码文章

Linux 环境下C语言编译实现贪吃蛇游戏
curse库的函数

猜你喜欢

转载自blog.csdn.net/m0_51039112/article/details/109062746