在 Linux 系统中,gcc
和 g++
是两个常用的编译工具,分别用于编译 C 和 C++ 代码。下面我将介绍gcc、g++的一些基本用法
目录
一、简单的认识
二、简单了解一下编译的过程
<1> 预处理阶段
<2>编译
<3>汇编
<4>链接
三、分别介绍编译过程
<1>预处理
<2>编译
<3>汇编
<4> 链接
<5>简单介绍一下动静态库
一、简单的认识
如果没有gcc / g++ ,用yum 安装一下即可。
下面先简单举个例子帮助理解
这里我先创建一个test.c文件(这里最好还是带后缀,不然gcc / g++是无法识别的)。
然后再退出vim , 通过gcc 命令编译该文件,形成一个新的可执行文件
这里系统会默认生成a.out的可执行文件,(如果想要修改可执行文件名,使用gcc -o 源文件 + 要生成的可执行文件名,这里gcc 后面的顺序是可以随意的,但是新的文件名要紧跟在 -o 后面)再用./a.out执行该命令。
(这里我忘记加换行符号,不好意思) ,如果我们用vim 打开这个可执行文件,会发现里面的东西我们看不懂,可执行文件是给cpu 执行的,而cpu 只认二进制的代码,所以我们的可执行文件就得是二进制的,我们的高级语言只是提高了编译的速度,并没有改变底层的原理。
另外一个需要注意的点就是,gcc 只能编译C语言的代码,g++可以编C语言跟C++的代码。
二、简单了解一下编译的过程
<1> 预处理阶段
1.头文件展开 头文件展开其实就是把 c / c++ 头文件中需要的部分拷贝到当前的文件当中。
2. 去注释
顾名思义,就是去掉代码中的注释
3.宏替换
将宏代码替换
4.条件编译
把条件通过的代码进行编译
在预处理后,文件里的代码还是C或C语言
<2>编译
把C / C++ 转成汇编代码
<3>汇编
把汇编转成二进制文件,这个二进制文件又叫可重定位二进制文件,这个文件是不能被执行的
<4>链接
三、分别介绍编译过程
程序的翻译一次性就会把上述的所有动作完成,所以我们就要通过不同的选项进行编译,形成特定的文件。
<1>预处理
这里我们可以使用-E选项编译文件,形成预处理完后的文件,(下面我选择的都是test.c 文件进行编译)
退出后,我们实行gcc -E test.c 命令,发现系统默认就会把预处理后文件内容全打印到屏幕上,这对于我们观察非常不方便,所以我们可以使用gcc -E test.c -o test.i 这里我们将test.c 预处理形成的文件打包形成一个test.i 的临时文件。一般来说,这里的临时文件一般就是把原文件名的后缀改成.i ,表示是预处理后形成的文件。
实行上述命令后,我们打开test.i 文件。我们可以发现文件多出来了很多的代码,这些代码其实就是stdio.h这个头文件里面的内容拷贝到test.i 这个文件里面,而这个过程就叫作头文件展开,包括一些注释也被去掉了,这里其实就是把去注释的过程。
这里我们再加入条件编译,看看预处理后的文件内容。
这里我们先写一段带条件编译的代码
然后我们退出去,用gcc -E a.cpp -o 1.cpp -D vscode2=2 (-D 其实就是定义一个宏,并且在编译器处理源代码之前处理,把这个宏插入进去)。打开1.cpp 这个临时文件,跳到最后几行
我们可以发现,只有条件编译通过的代码才被保留,其余的都被删除了,所以我们可以给编译器传不同的宏值,来对代码进行动态的裁剪。
<2>编译
编译过程其实就是把C语言代码转成汇编代码(其他语言也是差不多),我们可以用-S 选项,这个选项就是把从开始进行程序的翻译当编译工作做完,就停下来。这里我用test.i 这个文件来演示一下,我们可以用gcc -S test.i -o test.s 来形成一个test.s 的文件。
打开这里我们就可以看见,这里的代码全变成了汇编代码。
<3>汇编
就是把汇编的代码转成二进制文件,这里我们可以用-c 选项来实现该操作,这里我用 gcc -c test.s -o test.o 形成一个test.o文件(这里的o, 代表的是obj文件的缩写,也就是目标文件),这里我们运行一下命令,运行完后打开文件。
这里我们会发现,文件内容没法阅读,这是因为文件是二进制文件,但是vim是文本编辑器。所以会有这种情况的出现。正常来说文件内容已经是二进制,就应该能被执行,但是我们却执行不了(哪怕我们给它加上可执行权限)。
这是因为二进制文件里面有非常多的函数声明,我们必需要链接到库里面找到对应的函数,才能使文件变成可执行文件。
<4> 链接
我们先用gcc test.o -o test 形成一个叫test的可执行文件,我们可以用ldd 文件来查看可执行文件所依赖的库。这里的库一般分为静态库和动态库,在不同的系统库文件后缀不同
库 | Linux | windows |
动态库 | .so | .dll |
静态库 | .a | .lib |
这里我们用ldd 命令查看文件所依赖的库
这里我们依赖的库就是C标准库,这里我们的系统也是将C语言一些头文件和库下载好了,所以我们能就能再linux 中就能用C进行开发的原因 (安装环境其实也就是安装这些库跟头文件)。
用ls /lib64* 命令,查看当前系统下的相关库
<5>简单介绍一下动静态库
动静态库本质上也是文件,但是两者是有区别的(使用动态链接)
动态库就是被多个使用者共享使用,一旦缺失所有的用户都无法使用(使用静态链接)。
静态库就是把自己需要的文件拷到可执行文件中。
动态库 | 静态库 | |
优点 | 比较节省资源,不会有很多的重复代码 -- 这里的资源包括磁盘资源,内存,网络等等 | 不依赖库,同类型平台中可以直接运行使用 |
缺点 | 对库的依赖性比较强,一但库丢失,所有使用这个库的文件都将无法运行 | 可执行程序的体积较大,比较费资源 |
这里就不多介绍了,后面文件部分再详细介绍
以上就是全部内容,希望对各位读者有些许帮助。文中如有不当之处,还望各位大佬指正,谢谢!!!