首页 > 系统相关 >【Linux】gcc/g++使用

【Linux】gcc/g++使用

时间:2024-11-24 15:28:58浏览次数:8  
标签:gcc code ++ 汇编语言 C语言 编译 编译器 Linux

编译

我们知道,gcc只能编译C,g++既能编译C,也能编译C++。

由于两者的选项是相同的,这里我们使用gcc来说明。

这就是一个我们在linux中gcc编译一段代码后会自动生成一个a.out为名的可执行文件,然后我们./a.out,就可以执行这段代码。

我们也可以对生成的可执行程序的名称进行指定:

gcc code.c -o mycode

另种写法:

gcc -o mycode.exe code.c

程序的翻译过程

预处理(进行宏替换)
  1. 宏替换
  2. 去注释
  3. 头文件展开
  4. 代码裁剪

gcc -E code.c -o code.i这样可以让我们把预处理结果写入到一个临时文件code.i里。

-E的作用是,开始进行程序翻译,在预处理做完时就停下来。

vim code.i我们可以将其打开,发现我们源文件比code.i短了非常多:

我们可以打开这个系统自带的C语言开发环境。

可以看到这下面就包含了众多我们C语言中常见的头文件。

这也就是为什么我们的code.i这么大:因为头文件展开。

其实预处理完,我们的头文件就可以不需要了。

编译(生成汇编)

gcc -S code.i -o code.s这样我们就可以只进行编译这一步。

这就是汇编语言了。

-S是现在开始进行程序的翻译,但是把编译做完就停下。

汇编(生成机器可识别代码)

gcc -c code.s -o code.o

code.o这样的文件,我们把它叫做可重定位目标文件。在Windows中或者说在VS中,这种文件一般以XXX.obj的形式出现。

这种文件本身已经是二进制的了。

vim code.o我们还是可以看:

可以看到,我们直接这样看事一堆乱码。

但现在这个文件还是无法执行的。

因为这仅仅是把我们写的代码编成了二进制,但是我们源文件中还有很多的库方法,还没有关联起来。需要经过链接。

-C就是程序开始翻译,汇编完成就停下。

链接

gcc code.o -o code 这样就链接完了,形成了可执行程序code。

不过,这几个临时文件一般不会显示到磁盘上,而是在内存中就完成了。

怎么记住这几个选项呢?-ESc,是不是很像键盘左上角的键?

后缀是.iso,这个又怎么联想呢?镜像文件后缀一般是iso的。

如果我们gcc -c code.c不带生成文件名,一般形成的就是原名以.o后缀:code.o

我们一般喜欢先统一把源文件变成.o

然后gcc code.o code1.0 code2.o -o code然后把它们打包形成一个统一的可执行程序:

为什么喜欢这么做呢?

因为编译器在编译时不仅要形成可执行程序,有可能还要形成库,所谓库也就是把.o文件打了个包。

如果要形成库的话,就不需要形成可执行程序。

还有一个理由,在VS上也喜欢先变成.obj(相当于.o),最后再链接。

查看可执行程序依赖哪些库

ldd code我们就可以查看可执行程序依赖哪些库。

我们的源文件里用到的一些函数如printf,实现在C标准库里,所以我们的程序依赖C标准库,而它就是libc.so

我们用的C语言库是2.17版本的。

在任何平台下,库分两类。

在linux下,动态库一般以.so结尾。Windows中的动态库一般以.dll结尾。

在linux下,静态库一般以.a结尾。Windows中的静态库一般以.lib结尾。

我们linux中用的ls这些命令,通过ldd /usr/bin/ls,可以看到也依赖C标准库,所以可以看出这些命令是用C语言写的。

补充

条件编译

其实就是做代码裁剪

我们还可以这样(没定义M)

-D可以让我们命令行级别地进行宏定义,所以可以看到,gcc code.c -o code -DM是定义了M,所以就是专业版,下面的没有宏定义M,就是社区版。

也可以设置初始值:gcc code.c -o code -DM=100

编译器会把-DM=100解释为#define M=100,当做字符串插入我们的源文件再进行预处理。

条件编译的用途?

软件常分为社区版(免费)和专业版(收费),一般就是功能点差一些。其实公司内部只维护一份源代码,节省资源。发布时两者编译不同,功能拆分,条件编译来维护,进行代码裁剪。

linux操作系统也分为server服务器版,desktop版,虚拟机是后者。区别就是server版可能新增了一些开发工具,桌面相关的一些在编译时裁掉了。

还有,一些嵌入式设备不需要linux有那么多功能,可以裁掉。

linux的内核源代码也支持裁剪,不是由程序员手动去删的,是由条件编译来实现代码的动态裁剪的。

有的开发工具、应用软件既能在linux也能在Windows下跑,也是因为条件编译。发在哪个系统就把其他系统部分裁掉。

编程的本质就是在控制计算机。早期用的是计算机上的开关

然后产生了打孔编程(二进制编程)。

然后发明了汇编语言

这个助记符,也就是指令。

从汇编语言开始,就需要编译器这个东西了。

因为汇编语言也是文本,要由编译器映射成二进制。

有了汇编之后就慢慢有了C语言(70年代),C++,JAVA,GO等。

C语言也需要由C语言的编译器。也需要编译成二进制。

是直接把C语言变成二进制可执行程序,还是先翻译成汇编呢?

是后者。

  • 因为把C语言变成汇编还是从文本到文本,难度较低。
  • 另一方面汇编此时已经发展完善,只要将C语言翻译到汇编,汇编到二进制这部分工作就不需要做了。

这就是为什么我们翻译程序的过程中药先变成汇编语言,再变成二进制。

为什么有链接这一步?

我们不想在写程序前都还要写一遍printf等各种库函数的实现,所以就想要站在巨人的肩膀上,所以就需要库。

所以我们的代码编译好成为可重定位目标文件,然后和库进行链接,最后形成可执行。

(预处理展开的只是声明,因为头文件是公开的。头文件只有声明,没有实现。而形成可执行我们最终要的是方法。

C/C++是编译型语言,也为了让我们能进行库级别的开发,所以C/C++允许我们将头文件和源文件分开写。

其实写在一起更方便,但是分成头文件和源文件是因为C语言写的东西未来很多都要作为库,不想让人看到实现,但声明不得不给别人(得知道参数和返回类型)。)

说回编译器

C语言发明了,也需要有C语言的编译器来编译C语言,这个编译器至少要能把我们的语言翻译成汇编。

我们知道汇编语言也需要有编译器将其编译成二进制。那么,这个编译器自己应该用什么语言来写呢?

第一版编译汇编语言的编译器不可能用汇编写,是用二进制版的。

此时我们就可以编译汇编语言了。

但是编译器本身也是个软件,也有不同的版本。既然已经有了汇编语言和编译汇编语言的二进制版编译器,这时我们就可以用汇编语言来写一个汇编编译器了。

我们把用汇编语言写的这个汇编编译器再用二进制版的编译器编译一下,此后就不再需要二进制版本的汇编编译器了。我们就有了汇编语言写的汇编编译器。

这叫做编译器的自举过程


本文结束。
在这里插入图片描述

标签:gcc,code,++,汇编语言,C语言,编译,编译器,Linux
From: https://blog.csdn.net/2301_82135086/article/details/143955048

相关文章

  • linux之磁盘管理
    磁盘管理1.磁盘分类机械硬盘:盘片主轴传动手臂做机械运动类似DVD固态硬盘:内部是主板和U盘类似2.硬盘大小3.5英寸:台式机2.5英寸:笔记本服务器3.硬盘接口IDE接口过时scsi接口过时sata接口台式机3.0nvme接口固态硬盘SAS接口企业级4.硬盘存储......
  • 头歌实践教学平台——Linux 信号
    目录第1关:信号处理函数第2关:signal高级处理之sigaction第3关:Linux定时器第1关:信号处理函数    在主函数的最开始会初始化一个全部变量g_i4event为0。    本关的编程任务是补全右侧代码片段中两段Begin至End中间的代码,具体要求如下:      ......
  • 【C++】类(一):定义抽象数据类型
    类这部分内容对应于C++Primer第五版的第七章全部内容。原书当中的内容包括:7.1定义抽象数据类型;7.2访问控制与封装;7.3类的其它特性;7.4类的作用域;7.5构造函数再探;7.6类的静态成员;类的基本思想是数据抽象(dataabstraction)和封装(encapsulation)。数据抽象是一种依赖......
  • 实验四 c++
    任务一:task1_1.cpp:#include<iostream>usingstd::cout;usingstd::endl;//类A的定义classA{public:A(intx0,inty0);voiddisplay()const;private:intx,y;};A::A(intx0,inty0):x{x0},y{y0}{}voidA::display()const{......
  • 【C++】list容器及其模拟实现
    目录1.list的介绍及使用1.1list的介绍1.2list的使用1.2.1list的构造1.2.2listiterator的使用1.2.3listcapacity1.2.4listelementaccess1.2.5listmodifiers1.2.6list的迭代器失效2.list的模拟实现2.1模拟实现list2.1.1list节点2.1.2list常见功能......
  • 按键 芯片型号qt2160 linux驱动程序
    /*qt2160.c-AtmelAT42QT2160TouchSenseControllerThisprogramisfreesoftware;youcanredistributeitand/ormodifyitunderthetermsoftheGNUGeneralPublicLicenseaspublishedbytheFreeSoftwareFoundation;eitherversion2oftheLicense,o......
  • python VS c++
    一、语法特点Python:语法简洁、优雅,代码可读性极强,采用缩进来表示代码块,摒弃了像C++那样使用大括号的传统方式,使得代码看上去十分清晰简洁。例如:​if5>3:print("5大于3")elif5==3:print("5等于3")else:print("5小于3")​整个代码结构通过......
  • Linux-虚拟主机
    文章目录虚拟主机HTTPS本篇主要对于虚拟主机和CA的配置进行说明,不过对于CA的配置没有成功,配置成功的小伙伴欢迎指正问题......
  • C++-练习-99
    题目:编写一个程序计算流中第一个$之前的字符数目,并将$留在输入流中源代码:#include<iostream>intmain(){charinput;intcount=0;std::cout<<"Enteraphase:";while(std::cin.peek()!='$'){......
  • 探索 Linux 的 `/dev/shm`:高效共享内存的秘密
    探索Linux的/dev/shm:高效共享内存的秘密在Linux的日常使用中,你可能听说过/dev/shm这个目录,但它的用途和强大之处可能还不太清楚。其实,/dev/shm是一个内存文件系统(tmpfs),为我们提供了一种快速、高效的方式进行数据共享,尤其是在进程间通信的场景下。本文将通过简单的......