gcc/g++工具详解

发布时间:2024年01月12日

目录

一、安装gcc/g++

二、背景知识

三、相关选项

四、gcc如何工作

1.预处理

2.编译

?3.汇编

4.链接?

5.函数库的概念?

6.动静态库?


一、安装gcc/g++

gcc/g++ -v : 用来查看当前你使用的gcc/g++版本

?因为我的gcc/g++是升级过的所以版本更高,如果你用的是centos7.6的话你的gcc的版本可能是4.8的。

安装gcc/g++sudo yum install -y gcc-c++

这条指令会根据你当前的centos版本为你安装合适的gcc/g++版本。

gcc用来编译C语言代码,g++一般用来编译C++代码当然也可以用来编译C语言代码?

二、背景知识

在生成一个可执行程序文件的时候通常要经过如下几步:

  1. 预处理(a.去注释 b.宏替换 c.头文件展开 d.条件编译……)
  2. 编译(生成汇编)
  3. 汇编(生成机器可识别的代码)
  4. 链接(生成可执行文件或库文件)

三、相关选项

-E从现在开始进行程序的翻译,如果预处理完成,就停下来
-S从现在开始进行程序的翻译,如果编译完成,就停下来
-c从现在开始进行程序的翻译,如果汇编完成,就停下来
-o文件输出到文件
-static对生成的文件采用静态链接
-g生成调试信息
-shared对生成的文件采用动态链接
-O0不做任何优化
-O1尝试优化编译时间和可执行程序大小
-O2在O1的基础上进行更大力度的优化
-O3最高级别优化
-w不生成任何警告信息
-Wall生成所有警告信息

四、gcc如何工作

1.预处理

  • 预处理的功能主要包括宏替换,去注释,条件编译,头文件展开等。
  • 预处理的指令是以#号开头的代码行。
  • 指令:gcc -E mytest.c -o mytest.i
  • -E选项是从现在开始进行程序的翻译,如果预处理完成,就停下来。
  • -o选项是指目标文件。
  • ".i"文件是已经预处理过的C语言原始程序

 #include <stdio.h>
 
 #define NUM 20
  
 int main()
 {
    printf("NUM: %d\n", NUM);
    printf("hello world1\n");
  // printf("hello world2\n");
  // printf("hello world3\n");
  // printf("hello world4\n");
  // printf("hello world5\n");
    printf("hello world6\n");
                             
  //条件编译
  #ifdef DEBUG                 
    printf("hello debug!\n");
  #else
   printf("hello release!\n");
  #endif
   return 0;                                                                                                                                                                             
}

通过指令:gcc -E mytest.c -o mytest.i

?生成了一个mytest.i的文件,我们查看这个文件的内容如下

?这里我只截取了一部分,前面还有很多是头文件展开的内容。从这一部分我们不难看出预处理所做的工作。

2.编译

  • 在这个阶段中,gcc首先要检查代码的规范性以及是否有语法错误等等,检查无误后,gcc才会把代码翻译成汇编语言。
  • 指令:gcc -S mytest.i -o mytest.s
  • -S选项是从现在开始进行程序的翻译,如果编译完成,就停下来。

执行上面的指令后生成的“.s”文件内容如下

?3.汇编

  • 此阶段是把编译阶段生成的".s"文件转成目标文件
  • 指令:gcc -c mytest.s -o mytest.o
  • -c选项是从现在开始进行程序的翻译,如果汇编完成,就停下来。

?举个栗子:

执行上面的指令生成的mytest.o文件称为可重定向目标文件,可以查看这个文件的内容如下

?这里显示的都是乱码,我们也可以用od mytest.o进行查看,翻译过来都是二进制

4.链接?

  • 在成功编译之后,就进入了链接阶段
  • 指令:gcc mytest.o -o mytest
  • 生成的mytest文件即为可执行程序

5.函数库的概念?

首先看一个例子:

这个代码能编译通过吗?

答案是:可以的?

?因为它自动给你链接上了C语言的库

再看一个例子:

问:在上面的C语言代码中,并没有定义“printf”的函数实现,且在预编译中包含的“stdio.h”中也只有该函数的声明,而没有定义函数的实现,那么,是在哪里实现“printf”函数的呢?


系统把这些函数实现都被弄到名为 libc.so.6 的库文件中去了,在没有特别指定时,gcc 会到系统默认的搜索路径“/usr/lib”下进行查找,也就是链接到 libc.so.6 库函数中去,这样就能实现函数“printf”了,而这也就是链接的作用

?

上面中的?/lib64/libc-2.17.so 提供C语言的方法实现,/usr/include/stdio.h?提供C语言的方法列表,方法的声明。两者协同生成可执行程序。

6.动静态库?

一般链接的过程是有两种方式的:

a.动态链接 — 需要动态库

b.静态链接 — 需要静态库

在Linux中以.so结尾的称为动态库,.a结尾的为静态库

在Windows中以.dll结尾的为动态库,.lib结尾的为静态库

查看方式有两种:ldd+可执行程序文件名/file+可执行程序文件名

  • 静态库是指编译链接时,把库文件的代码全部加入到可执行文件中,因此生成的文件比较大,但在运行时也就不再需要库文件了。其后缀名一般为“.a
  • 动态库与之相反,在编译链接时并没有把库文件的代码加入到可执行文件中,而是在程序执行时由运行时链接文件加载库,这样可以节省系统的开销。动态库一般后缀名为“.so”,如前面图所示的 libc.so.6 就是动态库。gcc 在编译时默认使用动态库。完成了链接之后,gcc 就可以生成可执行文件,如下所示。 gcc test.o –o test
  • gcc/g++默认生成的二进制程序是动态链接的,这点可以通过 file 命令验证

?由图可以看出,静态链接的文件比动态链接的文件大得多了。

安装静态库的命令

C语言静态库安装:sudo yum install -y glibc-static

C++静态库安装:sudo yum install -y libstdc++-static

这次的内容就分享到这了,如有写的不好的地方还请指正,创作不易,如果你觉得写的好的话,就给博主三连吧,你的支持将是我的动力?

?谢谢!!!

文章来源:https://blog.csdn.net/m0_62537611/article/details/135515391
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。