ToB企服应用市场:ToB评测及商务社交产业平台
标题:
【Linux】编译器-gcc/g++使用
[打印本页]
作者:
梦见你的名字
时间:
2024-6-14 22:21
标题:
【Linux】编译器-gcc/g++使用
个人主页
: zxctscl
文章封面来自:艺术家–贤海林
如有转载请先关照
1. 前言
在之前已经分享了 【Linux】vim的使用,这次来看看在云服务器上的编译器gcc。
2. 初见gcc和g++
我们先写一段简朴的代码:
#include<stdio.h>
int main()
{
for(int i=0;i<10;i++)
{
printf("hello: %d\n",i);
}
return 0;
}
复制代码
当我们进行编译的时候:
发现根本就编译不了。
这个是因为编译器版本的题目:
查看编译器的版本:gcc -v
版本不是最新的,不支持在for里面界说变量。
假如想要支持,那么得加上这个下令:
gcc test.c -std=c99
复制代码
此时就编过了。
在用gcc时候有一个选项-o,后面接一个名称,就是把编译的可执行程序再起一个名字:
gcc test.c -o my.exe -std=c99
复制代码
-o也可以放在前面,但是-o紧跟的就是修改的文件名
gcc -o you.exe test.c -std=c99
复制代码
在Linux中以.cpp和.cc末了的都是c++代码
写一个简朴的C++代码:
#include<iostream>
using namespace std;
int main()
{
for(int i=0;i<10;i++)
{
cout<<"hello linux"<<i<<endl;
}
return 0;
}
复制代码
在这里编译这个C++代码
gcc test.cc
复制代码
就直接报错了
以是gcc不能用来编译c++代码。
因为gcc是用来编译C语言的,以是它不认识c++的语法。
以是编译c++代码得用g++:
g++ test.c
c
复制代码
假如想让编译c++代码时支持更高的特性,可以加上-std=c++11
g++ test.c
c
-std=c++11
复制代码
总之:
在编译C语言时候可以带上:std=c99;
在编译C++代码时可以带上:std=c++11.
那么g++能不能编译C语言的代码呢?
g++ test.c
复制代码
是可以的。
这个也和我们认知是一样的,c++兼容c。
以是
g++既能编译c++,又能编译C语言
。
假如想要编译一个指定名称的c++程序,怎么写呢?
同gcc一样,加上-o选项,-o后面紧跟着指定的名称:
g++ -o my.exe test.cc
复制代码
当然-o可以放在前面,也可以放在后面,和gcc的一样。
g++ test.c
c
-o you.exe
复制代码
同样c++代码的后缀还有.cpp。
将test.cc先改名为test.cpp:
mv test.cc test.cpp
复制代码
然后编译test.cpp,再指向a.out
C++代码后缀除了.cc和.cpp之外,还有一个.cxx
来直接编译一下:
g++ test.c
xx -o my.exe
复制代码
那么将后缀改为.txt能行吗?
mv test.cxx test.txt
复制代码
这里是不行的,Linux是不关心文件后缀的,但是编译器是关系。这里编译器就是把.txt当成文本文件了。
在之后的博客中都统一将C++后缀为.cc,因为最简朴。
想知道本身对应的g++是哪个版本的,就直接用下令:
g++ --version
复制代码
假如没有g++怎么安装呢?
可以直接在网上搜索,就会出来了
安装下令就是:
sudo yum install -y gcc-c++
复制代码
能直接将gcc-c++的标准库给装上了。
装好了,就能直接查看版本:
g++ --version
复制代码
3. 程序的翻译过程
程序的翻译过程:预处置处罚 编译 汇编 链接
先写一个简朴的代码,想看见每个阶段的编译结果
1 #include<stdio.h>
2 #define M 100
3
4 int main()
5 {
6 for(int i=0;i<10;i++)
7 {
8 printf("hello: %d\n,M:%d",i,M);
9 }
10 printf("hello gcc\n");
11 //printf("hello gcc\n");
12 //printf("hello gcc\n");
13 //printf("hello gcc\n");
14 //printf("hello gcc\n");
15 //printf("hello gcc\n");
16 //printf("hello gcc\n");
17 //printf("hello gcc\n");
18 //printf("hello gcc\n");
19 //printf("hello gcc\n");
20 //printf("hello gcc\n");
21 return 0;
22
23 }
复制代码
3.1 预处置处罚
预处置处罚:要做的是宏更换,去注释,头文件展开,条件编译。
3.1.1 宏更换 去注释 头文件展开
-E 就是从如今开始进行程序的翻译,预处置处罚完成,就停下。
gcc -E test.c -o test.i
复制代码
进入test.i
保存的就是-E后的结果
将test.c打开,对比发现test.i有800多行,是怎么来的?
是从test.c的头文件 #include<stdio.h>来的。
用来查看C语言标准的头文件库:
ls /usr/include/
复制代码
打开stdio.h发现有很多函数声明
vim /usr/include/stdio.h
复制代码
再打开test.i
vim test.i
复制代码
对比一下代码,发现宏已经更换了,而且注释了的代码也不在。
3.1.2 条件编译
先写一个代码在proj.c中:
1 #include<stdio.h>
2 int main()
3 {
4 #ifdef V1
5 printf("功能1\n");
6
7 #elif V2
8 printf("功能1\n");
9 printf("功能2\n");
10 printf("功能3\n");
11
12 #else
13 printf("功能1\n");
14 printf("功能2\n");
15 printf("功能3\n");
16 printf("功能4\n");
17 printf("功能5\n");
18 printf("功能6\n");
19 #endif
20
21 return 0;
22 }
~
复制代码
在编译之后打开proj.i
然后用宏界说将V1 定为1:#define V1 1
然后直接编译:
gcc proj.c
复制代码
发现结果只剩下功能1了。
就行打开proj.c,将#define V1 1 改为#define V2 1
编译运行后:
同样将v2改为v3.
这个就叫做条件编译,可以根据用户指明的条件,实现代码的动态裁剪。
在现实中,可以在软件维护一份代码,用条件编译的方式,来进行代码的裁剪,这样就能定制出各种功能的代码。
把宏删除。
用-D加上要宏界说的对象和值,再加上宏界说的文件,就可以直接对代码进行宏界说,更方便对代码进行裁剪
gcc -DV1=1 proj.c
复制代码
也可以裁剪其他的选项。
3.2 编译
编译:将C语言变成汇编语言。
-S:从如今开始进行程序的编译,编译完成绩停下来。
假如想要重新做一遍前面的预处置处罚再到编译,那么就用.c文件
gcc -S test.c -o test.s
复制代码
假如想要从预处置处罚阶段直接编译就用.i:
gcc -S test.i -o test.s
复制代码
这里发现报错,是因为版本的缘故原由
加上它提示的-std=c99就可以了:
gcc -S test.i -o test.s
-std=c99
复制代码
进入test.s看看
vim test.s
复制代码
发现里面是汇编语言。
3.3 汇编
汇编:将汇编语言翻译为二进制目标文件,这种二进制是没有办法指向的,还差一个链接。
-c:从如今开始进行程序的汇编,汇编完成绩停下来。
gcc -c test.s -o test.o
复制代码
这里的后缀.o,就是.obj,打开之前用vs写的程序,发现同样有。这个文件叫可重定位目标文件,不能直接执行,形成exe想要用到它。
打开这个test.o文件:
vim test.o
复制代码
发现里面形成乱码:
发现已经是二进制文件了:
file test.o
复制代码
那么能不能直接运行呢?
发现是不行的。
那么给它加上可执行的权限:
发现还是不能运行
一个文件能不能被指向,不止取决于它的权限,还要本身就是可执行程序。
得明白二进制目标文件是一个暂时文件,是不能够执行的。
3.4 链接
链接:将二进制目标文件形成可执行程序。
直接:
gcc test.o
复制代码
就形成可执行的目标文件了r
当然可以加-o带上形成的程序名:
gcc test.o
-o my.exe
复制代码
就能直接执行。
为了方便影象这些选项,观察一下可以发现它们连在一起就是:-ESc,只是E和S要大写。
后缀就是-iso,就像镜像文件。
4. 链接
链接是什么呢?
链接是我吗程序和库联合的过程。
语言肯定有本身的标准库,就像c中有c99标准,要保证跨平台性。
ldd后面接可执行程序就会显示它的动静态库
ldd my.exe
复制代码
最紧张的就是:
查看链接到的库
ls /lib64/libc.so.6 -l
复制代码
这里就是c标准库。
我们可以看看这个库的巨细:
ls /lib64/libc-2.17.so -l
复制代码
一般进行链接时是把程序和这个库链接形成一个可执行的程序。
这个库里面在不是库之前,是C语言标准库的源代码,像printf和各种方法,进行打包形成这个库。这个库的安全性是很高的。
怎么知道库里面有哪些文件?
会有一批对应的头文件,这个头文件相当于一个方法阐明。
以是安装开发环境是:安装C标准库和C头文件
库分为动态库和静态库。在Linux里面有,同样在windows里面也有。
在在Linux中库的真正的名字是把前缀lib去掉,去掉“.”后面的后缀。
以是这个就是c标准库。
因为Linux存在这两种库,就决定了,在链接时,有两种方式:
动态链接
和
静态链接
。
4.1 动态链接
举个例子:就像在学校旁边有个网吧,一个学长(相当于编译器)告诉了小明这个网吧的地址,(就相当于有了目标库的地址)这个地址就是,这个过程就是动态链接。
小明在这个网吧(就相当于动态库)的9号机(相当于库里面的一个方法,printf),当小明在学校里面作业(程序执行的代码)想要用到电脑,去了网吧(跳转到库)的9号机(想要的方法),用完之后回学校(返回程序),这个过程就是一次动态运行的过程。
在网吧被派出所查封以后,这个网吧就不能进了。也就是说
动态链接依赖动态库,一旦动态库缺失,全部静态链接,这个库的程序,都无法执行了。
c动态库,是默认提供的
gcc默认形成可执行程序,默认采取动态链接
。
查看文件类型:
file my.exe
复制代码
使用的是动态库链接:
动态库和动态链接的优缺点:
不能丢失
节省资源
重新创建一个文件夹,把test.c移动到里面,然后执行。
默认采取动态链接
4.2 静态链接
接上个例子:小明在买了网吧9号机器(库的方法),这样每次上网(执行程序)都能用,不须要这个网吧了,每次执行程序就拷贝到本身的电脑上,这个过程叫静态链接。这个网吧卖电脑就是静态库。
静态链接就是:在编译的时候,把库中的方法,拷贝到本身的可执行程序中。
静态库和静态链接的优缺点:
一旦形成,与库无关
浪费资源
形成静态链接:
gcc -o mytest-static test.c -static -
复制代码
发现报错了:
这个是因为在默认环境下,一般静态库都是默认没有安装的。
安装下令是:
sudo yum install -y glibc-static libstdc++-static
复制代码
然后再执行:
再ldd看看:
ldd mytest-static
复制代码
有题目请指出,各人一起进步!!!
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/)
Powered by Discuz! X3.4