首页 > 系统相关 >Linux编译过程以及生成中间文件--链接

Linux编译过程以及生成中间文件--链接

时间:2023-06-30 22:55:41浏览次数:48  
标签:文件 gcc -- 编译 int Linux main 链接

1、编译系统 C源文件到可执行文件共经历了4个过程。在使用GCC编译程序时,编译过程可以被细分为四个阶段,包括预处理、编译、汇编、链接   1、预处理 在预处理阶段,编译器主要作加载头文件、宏替换、条件编译的作用。一般处理带“#”的语句。   我们可以通过gcc 的 -E 选项进行查看,如下所示:   gcc -E main.c > main.i 编译器将main.c预处理结果输出 main.i 文件。   2、编译 在编译过程中,编译器主要作语法检查和词法分析。在确认所有指令都符合语法规则之后,将其翻译成等价的中间代码或者是汇编代码。   gcc -S main.i -o main.s 编译器将预处理结果文件main.i翻译成汇编代码main.s   3、汇编 汇编阶段是把编译阶段生成的”.s”文件转成二进制目标代码。   gcc -c main.s -o main.o 编译器将main.s文件转化为main.o 文件。   4、链接 在成功编译之后,就进入了链接阶段。链接就是将目标文件、启动代码、库文件链接成可执行文件的过程,这个文件可被加载或拷贝到存储器执行。   gcc main.o -o main.exe 编译器将main.o链接成最终可执行文件main.exe  

gcc -c与gcc -o以及不加参数的区别:

-c 编译和汇编,但不要链接。 -o <file> 将输出放入<文件>。 '无参数' 表示恢复为基于文件扩展名猜测语言的默认行为   1、通过gcc 不加参数可以一步直接编译生成可执行文件 gcc main.c 这里生成的是可执行文件a.out,当然可以通过-o选项更改生成文件的名字,比如将生成的可执行文件命名为hello.exe gcc main.c -o main.exe   //当然也可以通过-o选项更改生成的执行文件的名字   2、gcc -c 编译生成main.o gcc -c main.c   #生成main.o gcc main.o    #不加参数,gcc自动链接上一步生成的main.o来生成最终可执行文件a.out   2、静态链接 静态连接器以一组可重定向目标文件为输入,生成一个完全链接的可执行目标文件作为输出。链接器主要完成以下两个任务:
  • 符号解析:每个符号对应于一个函数、一个全局变量或一个静态变量,符号解析的目的是将每个符号引用与一个符号定义关联起来。
  • 重定位:链接器通过把每个符号定义与一个内存位置关联起来,然后修改所有对这些符号的引用,使得它们指向这个内存位置。
3、目标文件  
  • 可执行目标文件:可以直接在内存中执行;
  • 可重定向目标文件:可与其它可重定向目标文件在链接阶段合并,创建一个可执行目标文件;
  • 共享目标文件:这是一种特殊的可重定向目标文件,可以在运行时被动态加载进内存并链接;
4、动态链接 静态库有以下两个问题:
  • 当静态库更新时那么整个程序都要重新进行链接;
  • 对于 printf 这种标准函数库,如果每个程序都要有代码,这会极大浪费资源。
共享库是为了解决静态库的这两个问题而设计的,在 Linux 系统中通常用 .so 后缀来表示,Windows 系统上它们被称为 DLL。它具有以下特点:
  • 在给定的文件系统中一个库只有一个文件,所有引用该库的可执行目标文件都共享这个文件,它不会被复制到引用它的可执行文件中;
  • 在内存中,一个共享库的 .text 节(已编译程序的机器代码)的一个副本可以被不同的正在运行的进程共享。
  5、静态库编译与使用   库是预编译的目标文件(.o)的集合,它们可以被链接进程序。 标准系统库可在目录/usr/lib与/lib中找到。比如,在类Unix系统中C语言的数序库一般存储为文件/usr/lib/libm.a。该库中函数的原型声明在头文件/usr/include/math.h中。 C标准库本身存储为/usr/lib/libc.a,它包含ANS1/ISO标准指定的函数,比如printf。对每一个C程序来说,libc.a都默认被链接。   假设我们自己编译一个加法程序,和打印程序。 //mylib.h int myadd(int a, int b); void myprint( int s);    
//mylib.cpp
#include <iostream>
#include "mylib.h"
int myadd(int a, int b)
{
     return a + b;
}
void myprint( int s)
{
  std::cout << s << std::endl;
}

  

以通过下面两个命令将这两个函数编译成静态库。 gcc -c mylib.cpp -o mylib.o //产生目标文件 ar rcv libmylib.a mylib.o //将目标文件打包成静态库   使用C++编译的静态库 //main.cpp #include <iostream> #include "mylib.h" int main() {     myprint(myadd(1,2));     return 0; } 通过下面的命令(任选一种)将main.cpp与静态库进行编译。 g++ -o main main.cpp -L. -lmylib g++ -o main main.cpp libmylib.a    

标签:文件,gcc,--,编译,int,Linux,main,链接
From: https://www.cnblogs.com/liujiarui/p/17517989.html

相关文章

  • 递归算法理解 (一)
    Introduction递归算法是一种直接或者间接调用自身函数或者方法的算法。递归算法的实质是把问题分解成规模缩小的同类问题的子问题,然后递归调用方法来表示问题的解。递归算法对解决一大类问题很有效,它可以使算法简洁和易于理解。递归算法,其实说白了,就是程序的自身调用。它表现在......
  • XTTS系列之二:不可忽略的BCT
    重要系统Oracle数据库U2L迁移场景中,如果客户来问我建议,我都会回复说首选就是XTTS,除非XTTS经测试实在是无法满足停机窗口,否则就不要考虑OGG这类方案。换句话说,选择OGG做迁移的场景,都是没有其他办法时才会选用的方案了。而在这类XTTS的迁移项目中,我认为bct的技术是至关重要的,因......
  • hadoop如何为用户赋予操作权限
    #首先使用vi命令在hdfs-site.xml最后加上下面配置<property><name>dfs.permissions.superusergroup</name><value>自定义组名</value></property> #把用户添加到组,先进入root模式usermod-a-G组名<账号名> #给用户赋予所有权限 chown-R用户名:组名/usr/local/ha......
  • PTA题目集4、5以及期中考试的总结性Blog
    一、前言第4、5次大作业只有一题菜单的迭代,虽然题目量不多,但是难度却是大大增加,更加考验大家的学习自觉性和Java的功底,这两次的大作业均是在菜单系列-3的基础上迭代,是菜单系列-3的两个不同分支。自然而然,与菜单系列-3的代码结构的完整性和可复用性等关联就很大,菜单系......
  • Echart基本案例
    一、静态效果图 二,前期需要2.1、vue3项目,Echart引入2.2、原理解释略案例代码1:<template><divid="radarChart"style="width:100%;height:100%;"></div></template><scriptsetup>import*asechartsfrom'echarts'......
  • centos7安装nginx
    1.tar-zxvfnginx-1.6.2.tar.gz2.yuminstall-ygccpcre-develzlib-developensslopenssl-devel 3. ./configure4.删除-Werror,这个文件在/nginx-1.6.2/objs/Makefile 5. 删除下面这句话  文件在/src/os/unix/ngx_user.c ......
  • 开源通用高性能的分布式id序列组件
    原文地址:https://ntopic.cn/p/2023062101/Gitee源代码仓库:https://gitee.com/obullxl/sequence-jdbcGitHub源代码仓库:https://github.com/obullxl/sequence-jdbc分布式id序列说明业务数据的存储,少不了数据记录的id序列。id序列(或称序列)的生成方式有很多种,比如当前时间戳、......
  • [刷题记录]Leetcode列表专题
    No.1题目Leetcodelink思路数组本身是非降序,即最小值和最大值在数组的两端非降序数组每个元素平方后,最大值在两端,最小值在中部双指针比较数组两端最大值的大小,提取出最大的。移动双指针,然后得到次大,次次大,逐步得到结果注意left==right是有意义的,即待处理数组只有一个元素,......
  • String解析及其方法
    String解析及其方法1.前言2.什么是字符串(String)3.字符串(String)的两种创建方式及其区别4.字符串(String)的方法及其部分原码解析5.字符串(String)的弊端1.前言String类代表字符串。Java程序中的所有字符串字面值(如"abc")都作为此类的实例实现。字符串是常量;它们的值......
  • Sentinel的线程隔离与Hystix的线程隔离有什么差别?
    Hystix默认是基于线程池实现的线程隔离,每一个被隔离的业务都要创建一个独立的线程池,线程过多会带来额外的CPU开销,性能一般,但是隔离性更强。Sentinel是基于信号量(计数器)实现的线程隔离,不用创建线程池,性能较好,但是隔离性一般。......