linux查看gcc进程里面gcc是c语言编译器吗?

第一个程序可以编译通过:

第二个程序不能编译通过:

为什么在sqrt( )函数中,参数必须要写具体的实数,不能使用变量名呢?
如果不能用变量名,怎么实现变量值可以代入实参位置实现计算?

在线等待回复,最迟3小时内结贴。

1、gcc是一套编译工具集合,它包含了编译器,连接器等等工具链。可以编译c/c++/objc/java的主流常用语言,所以gcc是C语言编译器的理解是非常片面的。

  • gcc和g++都是gcc工具套件里面的命令
  • 只要是 GCC 支持的编程语言,都可以使用 gcc 命令完成编译,它根据文件后缀来自动选择要编译的语言,比如.c(C语言);.cpp(c++语言);.m(Objective-C);.go(go语言)
  • 而g++ 指令无论目标文件的后缀名是什么都按照编译 C++ 代码的方式编译

这里以C语言为例,它的编译流程如下:

  • 1、将C语言源程序预处理,生成.i文件
  • 2、预处理后的.i文件编译成为,生成.s文件。
  • 3、 将汇编语言编译成生成目标文件.o文件。
  • 4、将各个模块的.o文件链接起来生成一个可执行程序文件。

静态库和动态库可以理解为目标文件(.o)的集合,它们的区别就是在被连接到可执行程序中时:
静态库是直接拷贝到可执行程序中,而动态库则只是在可执行程序中保留一份动态库的说明信息,加载则分为程序加载时加载动态库和程序运行时加载动态库两种方式。

ar命令参数 r:表示向静态库中添加模块;c:表示静态库存在就替换 s:如果静态库中存在模块,则替换

    创建main.c内容如下:

-fPIC 表示生成位置无关代码,如果要让动态库再被多个程序引用时内存中也只有一份拷贝则编译动态库时必须要有此选项,否则和静态库一样了。

可以看到这里引用动态库和静态库的编译命令是一样的,默认情况下,如果当前目录中同时存在libmath.a和libmath.so库,gcc将优先引用动态库。

  • 5、查看可执行程序依赖的动态库

可以看到每一个程序,它都会默认链接libc.so这样一个C标准库

  • 6、动态库中引用静态库或者动态库
    编译动态库的流程原理和编译可执行程序中引用静态库与动态库一样,即如果引用静态库,那么最终生成的动态库中含有该静态库的一份拷贝,则该动态库被连接到可执行程序中时就不需要指明它引用的静态库了。如果引用动态库,那么最终生成的动态库中只是包含要引用动态库的一份信息说明,则该动态库被连接到可执行程序中时不仅要指明动态库还要指明动态库引用的动态库

tips:如果要编译一个静态库,而该源码中引用了另外的静态库或者动态库,则用ar打包为静态库时要手动将这些库都合并进来,否则这个静态库被连接到可执行程序时也需要同时指明这个静态库所引用的静态库或者动态库

然后将log.c编译为动态库

最后编译main.c可执行程序

可以正确连接和执行;如果换成如下的流程也是可以的

也就是说当编译动态库的时候,如果动态库中引用了静态库,可以不用显示指明对静态库的引用(即上面去掉-lmath -L./),只需再最终执行可执行程序连接阶段时指明即可;如果引用了动态库也是一样。所以充分说明了gcc -shared -o指令只是类似于ar的一个打包器,并不会调用连接器,只有gcc -o指令最终生成可执行程序时才会调用连接器

现在将log.c编译成静态库然后在main.c中引用

如果同时存在动态库和静态库连接器将优先选择动态库,所以这里通过gcc main.o liblog.a -o main 显示指定引用静态库log,同时还要显示引用math库,因为编译log库的时候并没有将math库合并进去

不管是静态链接还是动态链接都是在生成可执行程序时连接器的连接行为,他们的区别为:

  • 静态链接,只能用于静态库,连接器对要引用的库都会拷贝到可执行程序中
  • 动态链接,只能用于动态库,连接器对要引用的库都只会在可执行程序中保留一份库的引用信息,库要等到程序加载时或者运行时动态的载入内存
  • gcc默认情况下可同时引用动态库和静态库,如果要引用的动态库和静态库同时存在默认选择动态库,除非显示指明。如果用-static参数显示指定,那么只能引用静态库

这里有一点要注意,gcc编译器引用的标准C语言的库libc提供了libc.a和libc.so两份库

在理解符号决议的概念之前首先看一段常用的C语言代码(test.c)

// 定义未初始化的全局变量,该变量可以再其它文件中引用
// 定义初始化的全局变量,该变量可以再其它文件中引用
// 定义未初始化的全局私有变量变量,static声明后该变量只能再其本文件中引用
// 定义初始化的全局变量,static声明后该变量只能再其本文件中引用
// 声明全局变量,该变量定义在其它文件
// 声明函数,该函数定义在其它文件
// 声明并且定义函数,static声明后该函数只能在本文件使用
// 声明并且定义函数,该函数可以在本文件和其它文件使用

当该文件被gcc编译后成目标文件后(test.o),目标文件一般包括如下部分:

  • 符号表:描述源文件定义的变量和函数以及引用的变量和函数

所以编译阶段,对于源文件中引用的外部变量以及函数,只要找到了变量和函数声明即可通过编译,所以这也是前面提到的为什么在编译动态库的时候(就算动态库引用了其它库)不需要显示指明也可以通过编译的原因。

符号决议:存在于连接阶段,连接器将每个目标文件中引用的外部变量及函数的找出来,然后去其它目标文件中查找他们的定义,如果未找到那么符号决议失败,连接器将提示"undefined reference xxx错误"。

在将源代码编译为目标文件后会在目标文件中保留引用的函数以及变量的地址,该地址为相对目标文件的地址,连接阶段连接器会将各个目标文件的变量以及函数的地址重新调整规划以保证每个变量及函数的地址是唯一的,这个过程就称为重定位,重定位只是相对于静态链接来说的,动态链接的规则又不一样了。所以程序运行是的变量及函数地址是在连接阶段确定的(备注:这些地址都是虚拟内存地址,真实的地址会经过转换得到)

连接器工作原理系列:[]

  • 专业考题类型管理运行工作负责人一般作业考题内容选项A选项B选项C选项D选项E选项F正确答案 变电单选GYSZ本规程...

  • 好久没看C了,本来就忘得一干二净的,一脸懵逼的看着zend。 关于.c 和 .h 的区别 子程序不要定义在.h中。...

  • ORA-00001: 违反唯一约束条件 (.) 错误说明:当在唯一索引所对应的列上键入重复值时,会触发此异常。 O...

  • 项目组件化、平台化是技术公司的共同目标,越来越多的技术公司推崇使用pod管理第三方库以及私有组件,一方面使项目架构...

  • 你可以一天上九节课两节晚自习,你可以一天写完两支笔芯做至少三套卷子,你可以早起十分钟晚睡十分钟记几个单词和成语,你...

  • 宁可选择累死, 也不会选择懒死, 宁可选择战死 , 也不会选择饿死 , 只要有野心就能找到目标 , 只要不放弃就会...

  • 小儿戏蝶 蝴蝶翩翩飞 ,小儿戏性高。 你跑我追乐 ,山涧笑声飘。

  • JAVA语言的特点2.面向对象 Java语言最吸引人之处,就在于它是一种以对象为中心,一消息为驱动的面向对象的编程...

GCC 编译流程 原文阅读于 / GCC 编译器编译 C 语言程序时需要经过以下 4 步: (1) 将 C 语言源程序预处理,生成 .i 文件。 (2) 预处理后的 .i 文件编译成为汇编语言,生成 .s 文件。 (3) 将汇编语言文件经过汇编,生成目标文件 .o 文件。 (4) 将各个模块的 .o 文件链接起来生成一个可执行程序文件。 GCC

,头文件、宏处理 -S:仅编译汇编语言,不汇编链接 -c编译汇编目标代码(计算机可识别二进制),不链接标准库(或第三方库)

GCC 编译器编译一个C语言程序时需要经过以下 4 C语言源程序预处理生成.i文件预处理.i文件编译成为汇编语言生成.s文件汇编语言文件经过汇编生成目标文件.o文件各个模块.o文件链接起来生成一个可执行程序文件GCC 编译流程如下图所示: .i文件、.s文件、.o文件可以认为是中间文件或临时文件,如果使用 GCC 次性完成C语言程序编译,那么只能

gcc 所支持文件后缀 二、gcc编译过程 Gcc 编译流程分为了 4 选项 “-E”进行查看,该选项作用是让 Gcc

汇编语言代码文件汇编为.o目标文件过程。所生成目标文件作为下一步链接过程输入文件。   4链接链接过程就是多个汇编生成目标文件以及引用文件进行模块链接生成一个完整可执行文件。在链接...)、编译(Compilation)、汇编(Assembly)和链接(Linking)4 步骤。本节讲解如何对这4 步骤进行控制。   3.1编译过程简介   gcc一个程序文件编译成

.o文件。里面包含了对各个函数入口标记,描述,当程序执行时还需要链接(link).链接就是把多个.o文件链成一个可执行文件。如 GCC 编译器就可以指定 -c选项进行输出。打开是乱码。 例如:gcc...在其内写上预处理语句。 般是 .c 文件经过汇编器处理输出。 如 GCC 编译器就可以指定 -S 选项进行输出,且是经过预处理器处理了。 例如:gcc

我要回帖

更多关于 linux查看gcc进程 的文章

 

随机推荐