GCC背后的故事&C程序常量变量的地址分配

一、GCC的静态库与动态库

1. 用gcc生成.a静态库和.so动态库

创建函数前,要先准备源程序,并将函数库的源程序编写成.o文件

(1)编译生成程序hello.c、hello.h、main.c

先创建一个目录保存此次练习,创建test1.
![在这里插入图片描述](https://img-blog.csdnimg.cn/96b1fd8c5caf4548987b8182eb19d4dc.png)
然后用vim编写程序
![在这里插入图片描述](https://img-blog.csdnimg.cn/2d0b321ecec84ba59c1dfc9ad579eadf.png)
//hello.h
#ifndef HELLO_H
#define HELLO_H
void hello(const char*name);
#endif

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

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

(2)将hello.c编译成.o 文件
用gcc将hello.c文件编译为hello.o文件

输入:gcc -c hello.c

输入ls命令可以看到目录下面多了一个hello.o 文件。
在这里插入图片描述
(3)由.o文件创建静态库
静态库文件名的命名规范是以lib为前缀,紧接着跟静态库名,扩展名为.a。我们将创建的静态库名为myhello,则静态库文件名就是libmyhello.a。创建静态库用ar命令。

输入:ar -crv libmyhello.a hello.o

在这里插入图片描述
同样输入ls命令可以在目录下看到libmyhello.a。
(4)在程序中使用静态库
在程序main.c中包含了静态库的头文件文件hello.h,然后要在主程序main直接调用公函数hello,需要先生成目标程序hello。
方法一:

输入:gcc -o hello main.c -L. -lmyhello

方法二:

输入:gcc main.c libmyhello.a -o hello

方法三:

先生成mian.o
输入:gcc -c main.c
再输入可执行文件
输入:gcc -o hello main.o libmyhello.a

在这里插入图片描述
删除静态库文件,此时公用函数hello已经连接到目标文件hello中了。
在这里插入图片描述
(5)由.o文件创建动态库文件
动态库文件命名规范和静态库文件命名规范类似,即在动态库名增加前缀lib,但是扩展名为.so,动态库的创建用gcc来创建。

输入命令:gcc -shared -fPIC -o libmyhello.so hello.o

在这里插入图片描述
(6)在程序中使用静态库
先用gcc命令生成目标文件,然后运行,运行出错需要到/lib中找库文件,将文件libmyhello.so复制到目录/lib中就可以了(试过复制到/usr/lib中,发现没有那个文件目录)。
在这里插入图片描述
探究当静态库和动态库同名时,gcc命令会使用那个库文件。
首先删除.c和.h以外的其他文件
在这里插入图片描述
然后生成静态库文件和动态库文件
在这里插入图片描述
运行gcc命令来使用函数库myhello来生成目标文件hello,并运行程序hello
在这里插入图片描述

2、linux下静态库.a和库.so文件的生成和使用

创建一个作业目录test2保存此次练习
在这里插入图片描述
然后编辑四个文件A1.c,A2.c,A.h和test.c
在这里插入图片描述

//A1.c
#include<stdio.h>
void print1(int arg)
{
        printf("A1 print arg:%d\n",arg);
        }
//A2.c
#include<stdio.h>
void print2(char *arg)
{
        printf("A2 print arg:%s\n",arg);
}
//A.h
#ifndef A_H
#define A_H
void print1(int);
void print2(char *);
#endif
//test.c
#include<stdlib.h>
#include"A.h"
int main(){
        print1(1);
        print2("test");
        exit(0);
}

(1)静态库文件的生成与使用
生成目标文件
在这里插入图片描述
生成静态库.a文件
在这里插入图片描述
使用.a库文件,创建可执行程序
在这里插入图片描述
(2)共享库.so文件的生成与使用
生成目标文件
在这里插入图片描述
生成共享库.so文件
在这里插入图片描述
使用.so文件,创建可执行程序
在这里插入图片描述
在这里插入图片描述

二、Gcc连接函数与静态库文件

1、函数与静态库连接

在第一次作业的程序代码基础进行改编,除了x2x函数之外,再扩展写一个x2y函数(功能自定),main函数代码将调用x2x和x2y ;将这3个函数分别写成单独的3个 .c文件,并用gcc分别编译为3个.o 目标文件;将x2x、x2y目标文件用 ar工具生成1个 .a 静态库文件, 然后用 gcc将 main函数的目标文件与此静态库文件进行链接,生成最终的可执行程序,记录文件的大小。
(1)编写程序
编写x.c和x.h

//x.c
#include"x.h"
float x2x(int a,int b)//定义一个算数运算函数
{
        float c;
        c=(float)a/b;
        return c;//返回c的值
}
//x.h
#ifndef X_H
#define X_H
#include<stdio.h>
float x2x(int a,int b);
#endif

编写y.c和y.h

//y.c
#include"y.h"
float y2y(int a,int b)
{
        float c;
        c=(float)a/b;
        return c;
}
//y.h
#ifndef Y_H
#define Y_H
#include <stdio.h>
float y2y(int a,int b);
#endif

编写main.c

#include"x.h"
#include"y.h"
int main()
{
        int x=8,y=3;
        float c;
        c=x2x(x,y)+y2y(x,y);
        printf("%.2f\n",c);
        return 0;
}

(2)生成将.c 文件编译成.o文件

输入:gcc -c x.c y.c
输入:gcc -c main.c

在这里插入图片描述
(3)将目标文件用ar生成.a静态文件

输入:ar -crv libmain.a x.o y.o

在这里插入图片描述
(4)用gcc将main函数的目标文件与静态库文件连接,生成可执行程序

输入:gcc -o main main.o libmain.a
执行文件:./main

在这里插入图片描述

2、函数与动态库连接

用gcc生成三个.o目标文件后,将目标文件用ar工具生成一个.so动态库文件

输入:gcc -shared -fpic -o libmain.so x.o y.o

在这里插入图片描述
然后用gcc将main函数的目标函数与动态库文件建立连接,并且执行程序

输入:gcc -o main main.c -L. lmain
输入:./main

在这里插入图片描述
发现出现错误,此时需要进行下面操作

输入:sudo cp libmain.so /usr/lib

再次执行程序即可输出正确答案
在这里插入图片描述

三、总结

本文章学习的.a静态库文件和.so动态库文件的生成和使用,并将二者进行了对比,可以知道当静态库文件和动态库文件同名时,优先使用动态库文件。在学习的过程中出现了一点困难,当按照步骤一步一步来的时候会解决问题,也会越来越熟练。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值