【Linux】编译器-gcc/g++使用
个人主页 : zxctscl
文章封面来自:艺术家–贤海林
如有转载请先通知
文章目录
- 1. 前言
- 2. 初见gcc和g++
- 3. 程序的翻译过程
- 3.1 预处理
- 3.1.1 宏替换 去注释 头文件展开
- 3.1.2 条件编译
- 3.2 编译
- 3.3 汇编
- 3.4 链接
- 4. 链接
- 4.1 动态链接
- 4.2 静态链接
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.cc

如果想让编译c++代码时支持更高的特性,可以加上-std=c++11
g++ test.cc -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.cc -o you.exe


同样c++代码的后缀还有.cpp。
将test.cc先改名为test.cpp:
mv test.cc test.cpp

然后编译test.cpp,再指向a.out

C++代码后缀除了.cc和.cpp之外,还有一个.cxx

来直接编译一下:
g++ test.cxx -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 1003 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 V15 printf("功能1\n");67 #elif V28 printf("功能1\n");9 printf("功能2\n");10 printf("功能3\n");1112 #else13 printf("功能1\n");14 printf("功能2\n");15 printf("功能3\n");16 printf("功能4\n");17 printf("功能5\n");18 printf("功能6\n");19 #endif2021 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

有问题请指出,大家一起进步!!!
相关文章:
【Linux】编译器-gcc/g++使用
个人主页 : zxctscl 文章封面来自:艺术家–贤海林 如有转载请先通知 文章目录 1. 前言2. 初见gcc和g3. 程序的翻译过程3.1 预处理3.1.1 宏替换 去注释 头文件展开3.1.2 条件编译 3.2 编译3.3 汇编3.4 链接 4. 链接4.1 动态链接4.2 静态链接 1. 前言 在之…...
Python 中的 filter() 函数:筛选可迭代对象元素
在 Python 中,filter() 函数是一个非常有用的内置函数,用于根据指定条件过滤可迭代对象中的元素。本文将深入探讨 filter() 函数的用法、工作原理以及常见应用场景,以帮助大家更好地理解和运用这个函数。 什么是 filter() 函数? …...
Java高频面试之并发篇
有需要互关的小伙伴,关注一下,有关必回关,争取今年认证早日拿到博客专家 并行和并发有什么区别? 并行是同时执行多个任务,而并发是多个任务在一段时间内交替执行。并行(Parallel)是指同时执行多个任务或操作,通过同时…...
docker 运行异构镜像
概述 关于docker镜像在不同的cpu架构下运行报错的解决办法,作者踩坑验证,在此分享经验 某次工作遇到需要银行内部部署docker镜像,由于行内已经开始走信创的路线,使用鲲鹏系统,arm架构,记过就遇到了standa…...
练习3-8 查询水果价格
探索--题目集索引 给定四种水果,分别是苹果(apple)、梨(pear)、桔子(orange)、葡萄(grape),单价分别对应为3.00元/公斤、2.50元/公斤、4.10元/公斤、10.20元…...
PTA 对于下列程序,正确的是() 。void f(int *p){ *p = 5;}int main(void){ int a, *p; a = 10;
对于下列程序,正确的是() 。 void f(int *p) {*p 5; } int main(void) {int a, *p;a 10;p &a;f(p);printf(“%d”, (*p));return 0; }A.5 B.6 C.10 D.11 答:A 解析:这里考察当是指针作为函数的参数。这里将 p …...
【银河商学】大蓝短视频学习02——流量突围实战
【银河商学】大蓝短视频学习02——流量突围实战 内容大纲 找对标找准你的"竞争对手" 定形式选定适合你的视频形式 做内容选题决定命运 2s上热门 一、找对标 1. 为什么要找对标 标准答案,少走弯路99%的问题,都有标准答案。 找个懂得人问一问 秒上热门,快速起号预…...
Android 获取Sms
Android 获取Sms 本篇文章记录下android下获取短信列表. 1: 申请权限 <uses-permission android:name"android.permission.READ_SMS" />2: 获取短信内容列表 private void readSms() {String[] projection {"_id", "address", "b…...
【Linux】cpp-httplib库
目录 升级gcc版本 下载cpp-httplib的zip安装包,上传到服务器 编辑 简单使用 首先打开gittee,搜索cpp-httplib,选择其中一个即可 也可以点下方链接 cpp-httplib库:cpp-httplib: cpp-httplib (gitee.com) 注意:cpp-httplib在使用的时候需…...
全网最最最详细centos7如何安装docker教程
在CentOS 7上安装Docker主要包括以下步骤: 1. 卸载旧版本的Docker 首先,需要确保系统上没有安装旧版本的Docker。可以通过以下命令来卸载它们: sudo yum remove docker \docker-client \docker-client-latest \docker-common \docker-late…...
【C++专栏】C++入门 | 函数重载、引用、内联函数
博客主页:Duck Bro 博客主页系列专栏:C专栏关注博主,后期持续更新系列文章如果有错误感谢请大家批评指出,及时修改感谢大家点赞👍收藏⭐评论✍ C入门 | 函数重载、引用、内联函数 文章编号:C入门 / 02 文…...
html--彩虹爱心
文章目录 js内容cssreset.min.cssstyle.css html内容 js内容 const colors ["#e03776","#8f3e98","#4687bf","#3bab6f","#f9c25e","#f47274"]; const SVG_NS http://www.w3.org/2000/svg; const SVG_XLINK &q…...
基于Kronig-Penney能带模型的MATLAB求解与仿真
目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 5.完整程序 1.程序功能描述 基于Kronig-Penney能带模型的MATLAB求解与仿真.综合利用 MATLAB提供的求解常微分方程、矩阵行列式、代数表达式化简及绘图等函数 ,可使 Kronig-Penney能带模型分析…...
【Web - 框架 - Vue】随笔 - Vue CLI - 快速上手
Vue CLI 创建Vue CLI项目 【步骤】 命名项目空间:在电脑里创建文件夹,用于存储所有项目;定位项目空间:在"CMD窗口"里定位到工程的项目空间上; 方法1:(a)用"WINR"打开运行窗口&#x…...
JavaWeb开发——html、 jsp(html 、js 、java源码)
1.前后端整体合一 在页面上,包含界面和业务数据处理 2.前后端分离 项目整体上分成前端部分和后端部分,相互独立 Jquery的核心 选择器----找到需要操作的Dom读取或者设置DOM的值或者属性事件的处理 一、jQuery选择器 $("标签类型")$("…...
javascript事件大全
在JavaScript中,事件是用户和浏览器之间交互的桥梁。当某些特定的事情发生时(如用户点击按钮、鼠标移动、页面加载等),浏览器会触发相应的事件。这些事件可以被JavaScript代码捕获,并允许开发者执行某些操作。以下是一…...
太平医康养经理人是医疗资源的链接者
太平人寿通过构建资源整合平台,已成功将国际化医疗服务资源进行深度整合。目前,该公司已完成对英国著名医疗集团Circle Health在中国设立的首家医疗机构——圆和医疗的增资行动,并与新加坡知名的莱佛士私立综合医疗集团签订了业务合作协议。同…...
kafka(三)springboot集成kafka(1)介绍
基于kafka新版本 <dependencies><dependency><groupId>org.apache.kafka</groupId><artifactId>kafka-clients</artifactId><version>3.0.0</version></dependency> </dependencies> 一、kafkaProducer 1、介绍…...
Markdown语法与基础使用
在撰写博客、文档或者其他类型的文字内容时,Markdown语法是一种简洁、易读易写的标记语言,被广泛应用于互联网上的文本编辑和排版中。下面将介绍Markdown语法的基础使用方法,帮助你更好地利用Markdown来编写内容。 1. 标题 Markdown支持使用…...
【排序】七大排序表格比较
排序 时间复杂度 空间复杂度 最坏时间复杂度 最好时间复杂度 稳定性 插入排序 O(n) O(1) O(n) O(n) 稳定 希尔排序 O(nlogn)-O(n)取决于增量序列 O(1) O(n^1.3) O(nlogn) 不稳定 选择排序 O(n) O(1) O(n) O(n) 不稳定 冒泡排序 O(n) O(1) O(n) O(n…...
观成科技:隐蔽隧道工具Ligolo-ng加密流量分析
1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具,该工具基于TUN接口实现其功能,利用反向TCP/TLS连接建立一条隐蔽的通信信道,支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式,适应复杂网…...
Java - Mysql数据类型对应
Mysql数据类型java数据类型备注整型INT/INTEGERint / java.lang.Integer–BIGINTlong/java.lang.Long–––浮点型FLOATfloat/java.lang.FloatDOUBLEdouble/java.lang.Double–DECIMAL/NUMERICjava.math.BigDecimal字符串型CHARjava.lang.String固定长度字符串VARCHARjava.lang…...
屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!
5月28日,中天合创屋面分布式光伏发电项目顺利并网发电,该项目位于内蒙古自治区鄂尔多斯市乌审旗,项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站,总装机容量为9.96MWp。 项目投运后,每年可节约标煤3670…...
ElasticSearch搜索引擎之倒排索引及其底层算法
文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...
涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战
“🤖手搓TuyaAI语音指令 😍秒变表情包大师,让萌系Otto机器人🔥玩出智能新花样!开整!” 🤖 Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制(TuyaAI…...
MySQL中【正则表达式】用法
MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现(两者等价),用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例: 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...
大数据学习(132)-HIve数据分析
🍋🍋大数据学习🍋🍋 🔥系列专栏: 👑哲学语录: 用力所能及,改变世界。 💖如果觉得博主的文章还不错的话,请点赞👍收藏⭐️留言Ǵ…...
Device Mapper 机制
Device Mapper 机制详解 Device Mapper(简称 DM)是 Linux 内核中的一套通用块设备映射框架,为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程,并配以详细的…...
html-<abbr> 缩写或首字母缩略词
定义与作用 <abbr> 标签用于表示缩写或首字母缩略词,它可以帮助用户更好地理解缩写的含义,尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时,会显示一个提示框。 示例&#x…...
C#中的CLR属性、依赖属性与附加属性
CLR属性的主要特征 封装性: 隐藏字段的实现细节 提供对字段的受控访问 访问控制: 可单独设置get/set访问器的可见性 可创建只读或只写属性 计算属性: 可以在getter中执行计算逻辑 不需要直接对应一个字段 验证逻辑: 可以…...
