【Linux篇】gcc和g++的使用

💛不要有太大压力🧡
💛生活不是选择而是热爱🧡

在这里插入图片描述

前言

gcc是一个专门用来编译链接C语言的编译器

g++则是编译链接C++,也可以编译链接C语言

注意:gcc不能编译C++

安装

一般gcc都有,但是如果g++没有

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

查看版本:gcc -vg++ -v

C/C++程序编译链接过程

因为硬件的底层,是靠电路的正和负两种状态来实现的,对应就是0和1.所以计算机只认识二进制

程序翻译的过程实际上就是把程序转化成二进制的过程

  1. 预处理 (.c -> .i)

    1. 去注释
    2. 宏替换
    3. 头文件展开
    4. 条件编译

    注意:预处理之后还是C语言

  2. 编译

    C/C++ -> 汇编语言 (.s)

  3. 汇编

    汇编语言 -> 可重定向二进制目标文件(.o / .obj)

  4. 链接

    多个.o / .obj -> 合并成一个可执行文件 (.exe)

gcc的使用

gcc默认一步到位生成可执行程序

gcc test.c:直接生成可执行文件,默认名:a.out

gcc test.c -o test:生成叫test的可执行文件

也可以这样写:gcc -o test test.c

注意:-o 后面紧跟 要形成的文件名

gcc分步生成文件

  1. 预处理 (.c -> .i)

    gcc -E mytest.c :把预处理完成生成的内容 .i文件打印到屏幕

    gcc -E mytest.c -o mytest.i:把预处理生成的内容.i文件保存到 mytest.i 文件

    -o : 就是指定一个新的名字

    -E:从现在开始进行程序的翻译,如果预处理完成,就停下来

  2. 编译

    gcc -S mytest.i -o mytest.s:生成.s文件(汇编代码)

    -S:从现在开始进行程序的翻译,如果编译完成,就停下来

  3. 汇编

    gcc -c mytest.c -o mytest.o:生成.o文件(可重定向二进制目标文件),里面都是二进制

    -c:从现在开始进行程序的翻译,如果汇编完成就停下来

    可以用od mytest.o查看二进制文件

  4. 链接

    gcc mytest.o -o mytest:链接生成可执行文件mytest

巧记

过程:E S c -> 对应键盘的ESC建

文件:i s o -> 镜像文件的后缀

g++的过程和 gcc的程序翻译过程是一样的

动静态库

链接阶段,其实有一个重要的概念:函数库

[[对库的认识]]

写C/C++程序时,通常的做法是

func.h中包含自己写的函数的声明

func.cpp中包含函数的定义

test.cpp中测试代码

当test.cpp中包含了func.h文件后,也就是有了函数的声明。如果调用其中的函数,编译器就知道函数是存在的,会去别的地方找。

静态库/动态库与func.cpp的作用类似,包含了.h文件后,就去库中找对应的函数的实现,从而构成可执行程序

举个例子:

我们的C程序中,并没有定义“printf”的函数实现,且在预编译中包含的“stdio.h”中也只有该函数的声明,而

没有定义函数的实现,那么,是在哪里实“printf”函数的呢?

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

所以C程序是离不开C库文件的

并且,Linux下很多命令也是直接利用C语言写的,比如ls命令

通过ldd /usr/bin/ls就可以看到所依赖的库


函数库一般分为静态库和动态库两种,对应就有静态链接和动态链接

  • 动态库:

    在编译链接时并没有把库文件的代码加入到可执行文件中,而是在程序执行时由运行时链接文件加载库,这样可以节省系统的开销(也就是在本文件中加载所调用函数的地址,去调用)

  • 静态库:

    直接把库文件对应函数的代码全部加入到可执行程序中,因此生成的文件比较大,但在运行时也就不再需要库文件了

所以一般链接的过程有两种方式

  1. 动态链接 - 需要动态库
  2. 静态链接 - 需要静态库

[[动态库和静态库在不同系统的后缀]]

Linux下:.so(动态库),.a(静态库)

Windows下:.dll(动态库) ,.lib(静态库)

所以在安装VS2019等软件的时候,一并安装了C标准库的头文件和C标准库文件


链接之后,生成了可执行文件,我们可以查看生成的可执行文件的信息:ldd mytestfile mytest

其实最后生成的可执行文件 ,本身也是依赖于C语言的库的

如图可见 可执行文件的信息:

image-20220728152610753


汇编之后生成的.o文件已经是二进制了,为什么不能执行?

因为:生成的.o文件是自己写的代码翻译成了二进制的形式,但是你自己的代码中还有一些没有和库关联起来。调用的函数需要和库关联起来才能形成可执行文件。

其实就是 调用函数,实际上需要调用函数的地址,而如果不关联,就找不到函数的地址(是未定义的),自然就报错


动静态库的优缺点

静态库:

  • 优点:不依赖库,直接把调用的函数的代码加载到可执行文件,运行比较快
  • 缺点:占用资源(节省内存,磁盘空间等),静态库会被添加到和它连接的每个程序中, 而且这些程序运行时, 都会被加载到内存中. 无形中又多消耗了更多的内存空间

动态库:

  • 优点:因为只加载函数的地址,而不是函数的代码。生成的可执行文件小,节省空间
  • 缺点:由于运行时要去链接库会花费一定的时间,执行速度相对会慢一些

总的来说静态库是牺牲了空间效率,换取了时间效率,共享库是牺牲了时间效率换取了空间效率,没有好与坏的区别,只看具体需要了。

gcc/g++采用的链接方式

gcc和g++默认形成的可执行程序是动态链接的

事实上,动态链接形成可执行几乎是所有编译器的默认行为

(可以通过 lddfile命令查看)

image-20220728152610753

如何静态链接呢?

gcc tesc.c -o mytest_s -static: 生成采用静态链接的可执行文件 mytest_s(自定义命名即可,这里用s表示静态)

-static:表示用静态链接的方法形成可执行程序

image-20220728173035784

可以看到采用静态链接生成的可执行文件的大小 远大于 采用动态链接生成的可执行程序的大小(将近100倍)

注意:

动态链接必须使用.so动态库文件

静态链接必须使用.a静态库文件

而云服务器一般只有动态库没有静态库,如果使用静态库就会导致链接失败,需要安装

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

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

✨感谢阅读~ ✨
❤️码字不易,给个赞吧~❤️

在这里插入图片描述

  • 24
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值