gcc-g++使用编译链接理解

news2024/11/17 7:40:36

在讲gcc/g++使用之前我们先讲一下背景,编译链接

编译链接我们之前讲过一次,但是这里在深入理解一下编译链接,以及我们看一下现象

编译链接

首先,编译链接可以分为四步:

1.预处理

2.编译

3.汇编

4.链接

预处理

我们可以回忆一下之前说的预处理的作用,预处理的作用有下面几点

1.去注释

2.头文件展开

3.宏替换

4.条件编译

我们下面演示一下预处理后的程序

我们通过这条指令让code.c文件生成code.i文件,这条 指令后面会说到的,现在先看现象

头文件展开

我们前面的这个就是code.i文件,我们看到最开始是一些其他的代码,而这个就是头文件的展开,我们还可以看一下其他的代码

 

code.i文件件现在又八百多行,而前面就是头文件展开后的效果,剩下的就是原本的代码

那么我们现在看到了头文件的展开,我们还可以看一下宏的替换和去注释

去注释

 

这时候我们在源代码上注释了一些内容,我们预处理后的代码就没有了注释掉的内容,这个就是去注释,我们下面在看一下宏替换

宏替换

 

这次我们在源代码上加了#define N 99999,然后我们打印N,但是在我们的编译链接后,我们就是直接打印的是99999,这个就是宏替换,我们左后看一下条件编译

条件编译

我们先说一下什么是条件编译,我们经常听到说有些程序可以在64/32位下运行,或者是在windows/linux下跑,那么是什么原因呢?   就是条件编译,条件编译就是选择性的屏蔽或者是跳过或是执行某些代码,我们下面就来看一下条件编译

这个就是预处理做的事情,头文件展开 ,去注释,宏替换,条件编译

编译

编译:将预处理后的程序生成汇编代码

我们来看一下

这条指令就是将预处理后的code.i文件生成汇编代码,汇编代码我们一般用.s做后缀,这条指令也是后面会说到,现在只是看 现象

我们下面看一下生成的汇编代码

我们看到这就汇编代码,我们多少还是可以看明白一点的

编译 

 编译:将汇编代码编译为二进制机器码

上面的指令是将汇编编译为二进制机器码

我们看一下,编译生成的二进制机器码

 

上面的code.o是二进制文件,所以我们需要用二进制的工具查看

二进制文本查看工具 od file_name

 

但是我们还是看不懂

在讲链接之前,我们先讲一下我们刚才的所有的指令

gcc-g++ 指令

1.预处理指令

我们在看预处理后的文件我们是怎们看的?

就是这条指令,但是这条指令又什么作用呢? 

首先我们先看一下gcc,其实gcc和g++的使用方法时一样的,都是gcc [可选项] file_name [可选项]...

现在我们在来看一下这条指令,后面的指令也基本都是这样

1.gcc:就是使用的工具gcc/g++,也可以说时命令

2.-E:-E就是可选项,而-E的意思就是将该代码做完预处理就停止的意思

3.code.c:当然是文件名了,就是被编译的文件

4.-o:-o时可选项,意思是重命名,也有就是将预处理后的内容放在code.i的文件里面,而我们一般把预处理后的文件后缀叫.i文件

2.编译指令

这条命令就是编译的命令

我们这里只介绍一下-S的作用

1.-S: 就是编译的指令,告诉编译器,让编译器把该代码做完编译就可以了,也就是将该文件形成汇编代码就停止

所以-S,就是把文件形成汇编代码,而汇编代码一般的文件后缀为.s

3.汇编指令

这条指令就是形成二进制代码的指令

1.-c:意思就是告诉编译器,让编译器做完汇编就停止,也就是形成二进制机器码

而我们后面形成的文件是二进制文件,该文件叫做可重定向二进制目标文件,也叫做目标文件,虽然该文件时二进制文件,但是计算机并不可以执行,而该文件在windows里面也就是我们常见的.obj文件

链接 

链接:就是把目标文件链接起来,形成可执行程序

链接的指令

我知道这样说并不能明白链接时什么,所以这里我先介绍一下形成可执行程序的指令

这条指令我们没有带除了-o外的可选项,因为只要我们直接编译,我们就会生成可执行程序

 

我们看到我们形成了可执行程序,那么如果我们步带-o呢?

 

我们不带-o就是没有重命名,所以给我们默认名字a.out

所以我们平时编译程序只需要

gcc/g++ file_name -o/non -o(不带-o)新名称(不带-o当然不需要重命名)

链接的理解

我们刚才只是大概的说了一下什么时链接,就是将目标文件链接起来,形成对应的可执行程序,以及说了关于链接的指令

我们下面说一下关于链接的理解,当然现在也只是浅浅的谈一下

链接:

我们现在有一个程序,该程序里面又一个printf()函数,那么既然printf是函数,所以printf这个函数一定要有声明和定义,那么我们自己没有声明和定义该函数,是谁给我们做的呢?当然是写C语言的工程师了,那么我们也没有看到我们该函数定义在那里了

我们在想一下,我们C语言的程序时,我们会写什么#include<stdio.h>这个就是头文件,所以C语言的声明一定在这里面,但是只有C语言的声明有用吗?没有用,因为我们还需要定义,那么它的定义在那里呢?——库 里面

而我们用的C语言,所以我们用的库当然是C语言的库了,那么这个库又在那里呢?

在linux下,我们的C语言的库在/lib路劲下

所以我们的可执行程序都是需要链接的,我们需要把头文件和我们自己的文件链接起来,这样才可以形成可执行程序

查看程序连接库的指令 ldd

我们现在可以看一下我们刚才的代码链接的库

库的名字

我们看到我们上面的链接的这么长,但是并不是这样子的,我们库的实际名字是去掉前缀,去掉后缀,  libc.so.6....拿这个举例说明   

libc.so.6....    lib:就是前缀

libc.so.6....    .so:说明该库是动态链接的库(还有静态链接的库)也需要去掉

libc.so.6....    .6...:版本号也要去掉

libc.so.6....    所以我们库的真正的名字的 c

这个就是库的名词

动态库

我们刚才说了动态库和静态库,那么什么是动态库和静态库呢?

动态库:又称共享库,在链接后运行时需要库函数的时候去库里面找,所以我们一个动态库可能又多个程序使用

静态库

静态库:在编译链接的时候,将库里面的内容拷贝到自己的程序中,所以即使是将该可执行程序放在没有库的其他环境也可以运行

但是我们的云服务器一般是默认没有静态库的,所以我们需要自己yum安装静态库

安装静态库


sudo yum -y install glibc-static :C语言静态库


sudo yum install -y libstdc++-static :C++静态库

动静态库编译

我们的gcc/g++一般都是默认动态库编译,因为动态库编译需要耗费的资源少,所以我们的编译器都是默认动态

那么我们怎们样静态编译呢?

例如:

后面加 -static就是 默认静态编译

我们可以看到静态库编译后,占用的资源比动态库大好多倍

 

动静态库的优缺点

动态库:编译后占用资源少[优点],需要依赖库,一旦库被删除,或者丢失程序就无法运行[缺点]

静态库:并不依赖库,即使库丢失程序也可以运行[优点],占用资源多[缺点]

动静态库各有有缺点

debug和release

我们的程序在编译后,可能出现一些问题,所以这时候我们需要调试,但是我们直接编译时不可以调试的,我们需要加入调试信息

加入调试信息 -g

指令

 我们后面加-g就可以加入调试信息

所以我们加入调试信息后编译后的内容又大了一点

查看debug信息 readelf -S

readelf -S file.exe_name(可执行程序的文件名)可以查看debug信息

这里面就有调试信息

今天的gcc/g++的使用就到这里,gcc/g++的使用其实是一样的,但是gcc只能用来编译C语言,但是g++不仅可以编译C++还可以编译C语言,但是建议编译C++ 

 

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

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

相关文章

java Stream流

体验Stream流 案例需求 按照下面的要求完成集合的创建和遍历 创建一个集合&#xff0c;存储多个字符串元素把集合中所有以"张"开头的元素存储到一个新的集合把"张"开头的集合中的长度为3的元素存储到一个新的集合遍历上一步得到的集合 public class MyS…

NDK环境变量配置及Jni生成so文件

1、通过AndroidStudio下载NDK和Cmake之后&#xff0c;需要在系统环境变量中进行NDK的配置&#xff0c;如下 (1)、NDK_HOME : D:\SDK\Sdk\ndk\22.1.7171670 (2)、将%NDK_HOME%同时添加到Path中 2、在AndroidStudio的File->Project Structure->SDK Location中选择ndk&…

Linux Shell_cut命令(按列提取文本字符)

linux cut命令&#xff08;按列提取文本字符&#xff09; cut是一个选取命令&#xff0c;就是将一段数据经过分析&#xff0c;取出我们想要的。一般来说&#xff0c;选取信息通常是针对“行”来进行分析的&#xff0c;并不是整篇信息分析的 语法格式 cut [-bn] [file] 或 cu…

2023届-SLAM算法校招面经

23年6月初终于尘埃落定&#xff0c;今年受大环境影响&#xff0c;这一路可以说是步履维艰&#xff0c;我的投递的行业主要面向机器人和自动驾驶&#xff0c;投递岗位大部分是算法工程师&#xff0c;其中也包括C开发和少量的测试岗&#xff0c;在面试过程中加深了对车企、自动驾…

15天学会EasyX 第1天:EasyX的下载与配置安装

本文为山城瑞宝创作&#xff0c;转载请标注版权&#xff01; 本文所指的编译器为Dev-c&#xff0c;如果有任何问题请私信我。 如果是使用VS的伙伴&#xff0c;直接去官网一键安装就可以了&#xff08;会略讲&#xff09;。 EasyX官网地址&#xff1a;https://easyx.cn/ 目录 …

【模块七----面向对象基础部分】

面向对象基础部分 面向对象的编程思想介绍&#xff1a; 一 、类和对象&#xff1a;1.1类&#xff1a;创建对象前必须先有类的存在类和对象的关系&#xff1a;类的组成&#xff1a;属性行为类的创建实例&#xff1a; 1.2 对象&#xff1a;对象的创建格式&#xff1a;使用对象的成…

新来的00后这么猛,这薪资我看了都吓一跳,这是正常人吗?

2023年很卷吗&#xff1f;不&#xff0c;只能说你还得学&#xff01; 都说00后已经躺平了&#xff0c;但是有一说一&#xff0c;该卷的还是卷&#xff01; 这不&#xff0c;前段时间我们公司新招来了一个00后小伙&#xff0c;工作都没2年&#xff0c;跳槽到我们公司就起薪18K&…

MarkDown的基本使用方法

为了给官方的文档知识总结&#xff1a;Markdown 基本语法 | Markdown 官方教程 #空格内容&#xff1a;‘#’表示标题的等级&#xff0c;越少表示标题级别越高&#xff08;字越大&#xff09; 在一行的末尾加两个或多个空格再回车&#xff0c;就是我们普通的文本回车。【还有一…

FreeRTOS基础学习

一、学习资源&#xff1a; 1、正点原子免费教学视频&#xff1a; 原子哥&#xff0c;专注电子技术教学 2、FreeRTOS官方网站&#xff1a; FreeRTOS - Market leading RTOS (Real Time Operating System) for embedded systems with Internet of Things extensions 3、PPT与源码…

Node.js+vue多用户个人博客网站i03nz

基于nodejs语言设计并实现了个人博客。该系统基于B/S即所谓浏览器/服务器模式&#xff0c;应用Vue框架&#xff0c;选择MySQL作为后台数据库。系统主要包括首页、个人中心、用户管理、文章分类管理、博客文章管理、留言板管理、系统管理等功能模块。要循序渐进&#xff0c;心急…

chatgpt赋能python:Python列表分割与排序:完美解决数据处理问题

Python列表分割与排序&#xff1a;完美解决数据处理问题 在Python的开发实践中&#xff0c;数据处理是一项必不可少的操作。列表&#xff08;list&#xff09;是Python语言中常用的数据类型之一&#xff0c;列表中的元素可以是任意类型。列表的分割和排序是Python中常见的操作…

Apk编译过程1 - Android Studio 与 gradle

Apk编译过程1 - Android Studio 与 gradle 文章目录 Apk编译过程1 - Android Studio 与 gradlegradlewAndroid studio 的 gradle plugingradle脚本AGP&#xff1a;Android Gradle Plugin gradle 是 Android 开发者比较熟悉的构建工具了&#xff0c;因为 Android Studio 默认使用…

Java常用类及使用方法

目录 1.String 1.String的基本概念 2.String的不可变性 3.String的实例化方式及内存解析 1.两种方式 2.new构造器的方式的内存解析 3.字符串对象的存储 4.字符串拼接后的内存解析 6.String中的常用方法 7.什么时候indexOf (str)和LastIndexOf (str)返回值相同 8.Str…

用gpt定制一个pytest接口测试框(附源码)

目的&#xff1a; 描述我的需求和目标让gpt给我写一个测试接口框架 并且让他自己完善。 我说:帮我写一个基于python语言的 pytest的接口测试框架 支持post get put delete请求 添加详细的断言&#xff0c;处理身份验证和授权&#xff0c;处理HTTP错误 加上allure2报告和有请求…

代码随想录第51天

1.最佳买卖股票时机含冷冻期 淦&#xff0c;自己写&#xff0c;用3个状态死活写不出来。 动规五部曲&#xff0c;分析如下&#xff1a; 确定dp数组以及下标的含义 dp[i][j]&#xff0c;第i天状态为j&#xff0c;所剩的最多现金为dp[i][j]。 其实本题很多同学搞的比较懵&…

SecurityAccess(0x27)服务

SecurityAccess&#xff08;0x27&#xff09;服务 此服务的目的是提供访问数据和/或诊断服务的手段&#xff0c;这些服务因安全&#xff0c;排放或安全原因而受到限制。 用于将 例程或数据下载/上传到服务器和从服务器读取特定存储器位置的诊断服务是可能需要安全访问的情况。…

使用Inkscape绘制矢量电路图

GNU Inkscape是一个免费的开源矢量图形编辑器&#xff0c;非常适合画论文中的矢量插图。 Inkscape Inkscape支持win mac linux全平台&#xff08;下载&#xff09;&#xff0c;windows端还发布了uwp版本&#xff0c;可在Windows store安装。 基本操作&#xff1a; inkscape工…

2023年前端面试题汇总-性能优化

1. CDN 1.1. CDN的概念 CDN&#xff08;Content Delivery Network&#xff0c;内容分发网络&#xff09;是指一种通过互联网互相连接的电脑网络系统&#xff0c;利用最靠近每位用户的服务器&#xff0c;更快、更可靠地将音乐、图片、视频、应用程序及其他文件发送给用户&…

简谈软件版本周期 | Alpha、Beta、RC、Stable版本之间的区别

目录 &#x1f48c; 引言 ⭕ 软件版本周期 &#x1f6e0;️ 软件开发期 ⚖️ 软件完成期 &#x1f4b0; 商业软件版本 &#x1f48c; 引言 定义好版本号&#xff0c;对于产品的版本发布与持续更新很重要&#xff1b;但是对于版本怎么定义&#xff0c;规则如何确定&#x…

【微服务架构】无法在Sentinel Dashboard查看到服务的监控信息原因

&#xff08;目前项目中使用的Hystrix&#xff0c;而Hystrix已经不维护了&#xff0c;至今仍然是2018年发布的1.5.8版本。&#xff09; 开始学习一下新的服务治理框架Sentinel Sentinel官网介绍 在集成Sentinel案例中碰到的问题 微服务&#xff0c;无法在sentinel dashboard…