关于使用gcc在Linux系统中进行c语言程序的编译

1.可执行文件的组装

学习使用gcc生成静态库和动态库

在平时工作中,我们通常把公有函数制作成函数库,供其他程序使用,函数库又分为静态库和动态库。静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库。动态库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入,因此在程序运行时还需要动态库存在。

静态库生成

这里使用最简单的Hello World程序来演示。

  1. 创建hello.c和main.c文件
    使用touch命令创建
touch hello.c
touch main.c

使用vi对程序进行编译

vi hello.c
vi main.c

hello.c

#include <stdio.h>
void hello()
{
	printf("Hello World\n");
}

main.c

#include <stdio.h>
main()
{
	hello();
	return 0;
}
  1. 将hello.c编译成.o文件
    输入以下命令,即可形成
gcc -c hello.c
  1. 由.o文件生成静态库
    使用 ar 命令,即可生成.a文件
ar -crv libhello.a hello.o

在这里插入图片描述
注:静态库文件名的命名规范是以 lib 为前缀,紧接着跟静态库名,扩展名为.a。

  1. 在程序中使用静态库
    使用命令
gcc main.c libhello.a -o hello

从静态库中将公用函数连接到目标文件中
生成目标文件hello
在这里插入图片描述

  1. 运行hello程序
    在这里插入图片描述

动态库生成

  1. 由.o文件生成动态库
    使用命令,生成.so文件
gcc -shared -fPIC -o libhello.so hello.o

在这里插入图片描述

  1. 在程序中使用动态库
    使用命令
gcc main.c libhello.so -o hello
  1. 运行程序
    在这里插入图片描述

使用实例

静态库使用

  1. 编辑x2x和x2y函数,实现计算两个数的加减运算

x2x

int x2x(int a, int b) 
{
	return a+b;
}

x2y

int x2y(int a, int b) 
{
	return a-b;
}

main

#include<stdio.h>
int main() 
{
        int a=2;
        int b=3;
        printf("a+b=%d\n",x2x(a,b));
        printf("a-b=%d\n",x2y(a,b));
}
  1. 使用gcc命令生成3个.o文件
    在这里插入图片描述
  2. 将x2x、x2y目标文件用 ar工具生成1个 .a 静态库文件
ar -crv libsub.a sub1.o sub2.o

在这里插入图片描述

  1. 用 gcc将 main函数的目标文件与静态库文件进行链接,生成最终的可执行程序
gcc main.c libsub.a -o main
  1. 运行程序
    在这里插入图片描述
    其文件大小为
    在这里插入图片描述

动态库使用

  1. 由.o文件生成动态库
    使用命令,生成.so文件
gcc -shared -fPIC -o libsub.so sub1.o sub2.o
  1. 用 gcc将 main函数的目标文件与动态库文件进行链接
gcc main.c libsub.so -o main2
  1. 运行程序
    在这里插入图片描述
    出现错误,找不到动态库文件
    解决方法:将.so文件复制到lib文件夹里面
sudo cp libsub.so /usr/lib

重新运行
在这里插入图片描述
成功
文件大小为:
在这里插入图片描述
结论:使用静态库生成的目标程序比使用动态库生成的目标程序大

2.gcc编译的各种工具

关于gcc编译器下的工具

Binutils

Binutils是一组二进制程序处理工具,包括以下几种
(1) addr2line:用来将程序 地址转 换成其所 对应的程序源文件及所对应的代码行,也可以得到所对应的函数。该工具将帮助调试器在调试的过程中定位对应的源代码位置。
(2) as:主要用于汇编。
(3) ld:主要用于链接。
(4) ar:主要用于创建静态库。
(5) ldd:可以用于查看一个可执行程序依赖的共享库。
(6) objcopy:将一种对象文件翻译成另一种格式,譬如将.bin 转换成.elf、或
者将.elf 转换成.bin 等。
(7) objdump:主要的作用是反汇编。
(8) readelf:显示有关 ELF 文件的信息。
(9) size:列出可执行文件每个部分的尺寸和总尺寸,代码段、数据段、总大小
等。

c运行库

C 语言标准主要由两部分组成:一部分描述 C 的语法,另一部分描述 C 标准库。C 标准库定义了一组标准头文件,每个头文件中包含一些相关的函数、变量、类型声明和宏定义,譬如常见的 printf 函数便是一个 C 标准库函数,其原型定义在 stdio 头文件中。
C 语言标准仅仅定义了 C 标准库函数原型,并没有提供实现。因此,C 语言编译
器通常需要一个 C 运行时库(C Run Time Libray,CRT)的支持。C 运行时库又常简称为 C 运行库。与 C 语言类似,C++也定义了自己的标准,同时提供相关支持库,称为 C++运行时库。

gcc的编译过程

gcc的编译过程分为4步:预编译,编译,汇编,链接
这里使用一个简单的程序来演示这个过程
当使用gcc直接编译以下代码时

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

只需要使用

gcc hello.c -o hello

就能生成可执行文件
把编译过程分为四步

  1. 预编译
 gcc -E hello.c -o hello.i

以输出 的hello.i 文件中存放着 hello.c 经预处理之后的代码

  1. 编译
gcc -S hello.i -o hello.s

预处理之后,直接对生成的 hello.i 文件编译,生成汇编代码

  1. 汇编
gcc -c hello.s -o hello.o

对生成的汇编代码文件 hello.s,gas 汇编器负责将其编译为目标文件

  1. 链接
gcc hello.o -o hello

将生成的 hello.o 与C标准输入输出库进行连接,最终生成程序 hello

运行程序
在这里插入图片描述

用nasm汇编编译器编译生成执行程序

nasm安装过程不在此赘述

  1. 创建hello.asm文件
touch hello.asm
  1. 编译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         ; 调用内核功能

  1. 编译文件
nasm -f elf64 hello.asm
  1. 链接文件
ld -s -o hello hello.o
  1. 运行程序
./hello

在这里插入图片描述
成功
在这里插入图片描述
在这里插入图片描述
可以看到由nasm生成的程序大小比C代码的编译生成的程序小的多

3.库函数的运用

从光标库(curses)的主要函数功能了解库函数的作用

curses是一个在Linux/Unix下广泛应用的图形函数库,作用是可以在终端内绘制简单的图形用户界面。

其基本函数名称和功能
1、move(y,x);将光标移动至(x,y)处。

2、refresh();我们写入的内容首先会在系统缓冲区中,经过refresh()函数刷新之后才能够显示到屏幕上。

3、echo()和noecho();输入的字符显示和不显示在终端上。可以用密码输入。

4、输出:
addch();显示一个字符
addstr();显示一串字符串
printw(“格式”,变量);显示指定格式的内容,类似于printf();
mvaddstr();移动到某个位置输出。

5、输入:
getch();输入一个字符
getstr();输入一串字符串
scanw("%s",s);;按指定格式输入内容,类似于scanf();
mvaddstr();移动到某个位置输入。

在Ubuntu中安装curses库

输入命令,安装

sudo apt-get install libncurses5-dev

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

创建文件后将代码放进文件中
使用以下命令进行编译

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

在这里插入图片描述
成功运行

4.参考资料

Linux 环境下C语言编译实现贪吃蛇游戏:
http://www.linuxidc.com/Linux/2011-08/41375.htm

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值