【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

使用的是动态库链接:
在这里插入图片描述
动态库和动态链接的优缺点:

  1. 不能丢失
  2. 节约资源

在这里插入图片描述
重新创建一个文件夹,把test.c移动到里面,然后执行。
在这里插入图片描述
默认采用动态链接
在这里插入图片描述

4.2 静态链接

接上个例子:小明在买了网吧9号机器(库的方法),这样每次上网(执行程序)都能用,不需要这个网吧了,每次执行程序就拷贝到自己的电脑上,这个过程叫静态链接。这个网吧卖电脑就是静态库。
在这里插入图片描述

静态链接就是:在编译的时候,把库中的方法,拷贝到自己的可执行程序中。

静态库和静态链接的优缺点:

  1. 一旦形成,与库无关
  2. 浪费资源

在这里插入图片描述
形成静态链接:

gcc -o mytest-static test.c -static -

发现报错了:
在这里插入图片描述
这个是因为在默认情况下,一般静态库都是默认没有安装的。

安装命令是:

 sudo yum install -y glibc-static libstdc++-static

然后再执行:
在这里插入图片描述
再ldd看看:

ldd mytest-static

在这里插入图片描述

有问题请指出,大家一起进步!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/733115.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

吴恩达机器学习-可选实验:特征缩放和学习率(多变量)

文章目录 目标工具概念问题陈述数据集多变量梯度下降学习率a9.9e-7a9e-7a1e-7 特征缩放实现 恭喜致谢 目标 在本实验中&#xff0c;你将: 利用在上一个实验中开发的多变量例程对具有多个特征的数据集运行梯度下降探讨学习率alpha对梯度下降的影响通过使用z-score归一化的特征…

域控操作十:安装包exe转msi软件下发

需要的文件 Advanced Installer 软件用来将exe转换成msi因为域控只能下发msi格式 一个exe安装包这里拿微信举例 一个没有密码的共享文件夹 1.exe转MSI 2&#xff0c;开始下发 服务器和用户刷新策略 #完成

某品零食交易平台设计与实现|基于springboot+ Mysql+Java的某品交易平台设计与实现(源码+数据库+文档+PPT)

目录 基于springboot MysqlJava的某品交易平台设计与实现 摘 要 系统详细设计 数据库设计 论文参考 源码获取 文末获取源码联系 基于springboot MysqlJava的某品交易平台设计与实现 摘 要 随着科学技术的飞速发展&#xff0c;社会的方方面面、各行各业都在努力与现代的…

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…

Spring Boot 多环境配置

Spring Boot 多环境配置 在现代的软件开发中&#xff0c;通常需要将应用程序部署到不同的环境中&#xff0c;如开发环境、生产环境和测试环境等。每个环境可能需要不同的配置参数&#xff0c;例如数据库连接信息、日志级别等。在 Spring Boot 中&#xff0c;我们可以通过简单的…

智慧库室管控系统-智慧枪弹管控系统

项目背景&#xff1a; 针对部队装备管理现状&#xff0c;部队在进行硬件系统建设的同时&#xff0c;需通过装备管理系统软件的建设&#xff0c;综合集成监控、报警、出入库、信息发布、库管理、监测、防护等系统&#xff0c;对装备进行立体监控、实时预警、快速处理&#xff0…

springboot255基于spring boot的疫情信息管理系统

疫情信息管理系统的设计与实现 摘要 近年来&#xff0c;信息化管理行业的不断兴起&#xff0c;使得人们的日常生活越来越离不开计算机和互联网技术。首先&#xff0c;根据收集到的用户需求分析&#xff0c;对设计系统有一个初步的认识与了解&#xff0c;确定疫情信息管理系统…

【每日刷题】栈与队列-LC394、LC347、LC215

题外话&#xff1a;感觉脑子没长到栈这块…最近刷栈的题都好难啊…哭哭…坚持坚持&#xff01;多刷几遍就好了&#xff01;&#xff01; 1. LC394.字符串解码 题目链接 先说数据结构。 维护两个栈&#xff1a;一个栈存之前的字符串&#xff0c;另一个栈存之后的字符串的重复…

基于命名实体链接的事件抽取与知识图谱在电商领域的应用

开源项目推荐 多模态AI能力引擎平台: 免费的自然语言处理、情感分析、实体识别、图像识别与分类、OCR识别、语音识别接口&#xff0c;功能强大&#xff0c;欢迎体验。 多模态AI能力引擎平台: 免费的自然语言处理、情感分析、实体识别、图像识别与分类、OCR识别、语音识别接口…

mysql | 查询数据的过程|优化-->索引 |存储引擎

查询的过程 首先确认mysql 服务器是否启动 systemctl mysqld status 登录连接 mysql -h i p − u ip -u ip−uuser -p (-h 指定服务器ip -u 指定用户名 -p 指定密码) mysql 数据包 经过抓包分析&#xff08;mysql包其实就是基于tcp协议 3306端口) 传输采用mysql 协议&#xff0…

云原生构建 微服务、容器化与容器编排

第1章 何为云原生&#xff0c;云原生为何而生 SOA也就是面向服务的架构 软件架构的发展主要经历了集中式架构、分布式架构以及云原生架构这几代架构的发展。 微服务架构&#xff0c;其实是SOA的另外一种实现方式&#xff0c;属于SOA的子集。 在微服务架构下&#xff0c;系统…

Web本体语言OWL

语义网&#xff08;Semantic Web&#xff09;&#xff1a; 语义网是万维网联盟&#xff08;W3C&#xff09;提出的一种愿景&#xff0c;旨在增强现有Web的表达能力和智能处理能力&#xff0c;通过标准化的技术手段赋予网络数据更加精确和可计算的语义&#xff0c;使得机器能够…

ReactNative项目构建分析与思考之react-native-gradle-plugin

前一段时间由于业务需要&#xff0c;接触了下React Native相关的知识&#xff0c;以一个Android开发者的视角&#xff0c;对React Native 项目组织和构建流程有了一些粗浅的认识&#xff0c;同时也对RN混合开发项目如何搭建又了一点小小的思考。 RN环境搭建 RN文档提供了两种…

西门子PLC中的程序块及类别详解

在PLC的编程中&#xff0c;程序块是指一组逻辑控制代码&#xff0c;用于实现系统中特定的控制功能。程序块主要分为四类&#xff0c;包括函数块&#xff08;FB&#xff09;、函数&#xff08;FC&#xff09;、数据块&#xff08;DB&#xff09;和组织块&#xff08;OB&#xff…

300分钟吃透分布式缓存-24讲:Redis崩溃后,如何进行数据恢复的?

Redis 持久化是一个将内存数据转储到磁盘的过程。Redis 目前支持 RDB、AOF&#xff0c;以及混合存储三种模式。 RDB Redis 的 RDB 持久化是以快照的方式将内存数据存储到磁盘。在需要进行 RDB 持久化时&#xff0c;Redis 会将内存中的所有数据以二进制的格式落地&#xff0c;每…

Python算法题集_在排序数组中查找元素的第一个和最后一个位置

Python算法题集_在排序数组中查找元素的第一个和最后一个位置 题34&#xff1a;在排序数组中查找元素的第一个和最后一个位置1. 示例说明2. 题目解析- 题意分解- 优化思路- 测量工具 3. 代码展开1) 标准求解【二分法两次左边界】2) 改进版一【二分法左右边界】3) 改进版二【第三…

基于YOLOv8深度学习的葡萄病害智能诊断与防治系统【python源码+Pyqt5界面+数据集+训练代码】深度学习实战

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 ✌更多学习资源&#xff0c;可关注公-仲-hao:【阿旭算法与机器学习】&#xff0c;共同学习交流~ &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 《------往期经典推…

寻找完全平方数——浮点数陷阱

【题目描述】 输出所有形如aabb的4位完全平方数&#xff08;即前两位数字相等&#xff0c;后两位数字也相等&#xff09;。 【解析】 一、问题分析 从问题出发&#xff0c;题目要求输出的是满足一定条件的数。数在计算机中是要占存储空间的&#xff0c;要在计算机中表示一个…

C语言字符串型常量

在C语言中&#xff0c;字符串型常量是由一系列字符组成的常量。字符串常量在C中以双引号&#xff08;"&#xff09;括起来&#xff0c;例如&#xff1a;“Hello, World!”。字符串常量在C中是不可变的&#xff0c;也就是说&#xff0c;一旦定义&#xff0c;就不能修改其内…

Web自动化测试流程:从入门到精通,帮你成为测试专家

摘要&#xff1a; Web应用程序在今天的软件开发中占据着越来越重要的地位。保证Web应用程序的质量和稳定性是非常必要的&#xff0c;而自动化测试是一种有效的方法。本文将介绍Web自动化测试流程&#xff0c;并提供代码示例。 步骤一&#xff1a;选取测试工具 选择适合自己团…