转载请注明出处
Windows下C++编程,通过VC生成工程,编写C++源文件,点运行,代码没问题直接出结果。VC什么都帮我们搞了,不了解其中过程也完全没问题。
转到linux下写c++,总觉得有点虚,毕竟很多时候需要自己去构建。网上找了一些相关的文章,大多讲得高深,弄懂其过程后来写一篇不高深但易懂的,方便回忆。有不准确的地方欢迎指正。
 
C++包括源文件(.cpp)和头文件(.h),头文件包含变量的声明和类定义,源文件包含变量的定义。当然你也可以只用源文件来组织程序,但使用.h文件可以使程序结构更清晰。
linux下,c++生成二进制文件通常使用1条命令即可
  g++ source1.cpp source2.cpp source3.cpp -o main
其实这过程包含预处理、编译和链接3个过程,预处理包含宏定义、包含指令和条件编译指令。
 
宏定义是简单的替换,将某个变量值替换为另一个内容,之前学C的时候把它当全局变量使用(#define PI 3.14),包含指令可以包含其他C++文件,一般包含.h文件,预处理后可以将包含的.h文件内容展开(.h文件中包含的文件也被展开)。条件编译利用宏定义和包含指令,对代码展开内容做控制。比如:main.cpp中include "student.h"、include "teacher.h",student.h文件中又include "teacher.h",那么teacher.h被include了2次,Teacher类重复定义,编译会报错。在Teacher.h中可以使用条件编译(#ifndef _TEACHER_H #define _TEACHER_H ... #endif),保证Teacher定义只有一次。
 
编译过程将每个编译单元的代码翻译为机器码,每个编译单元产生一个目标文件(包含未解决符号表、导出符号表、地址重定向表和机器码)。变量、函数分为外链接(extern,符号导出)和内链接(static,符号不导出)
static和extern
  static:在example.h文件中全局范围内定义的变量x,变量a只可以在本编译单元内使用,不对外暴露该变量(链接时不会令其他编译单元拿到该变量)。所以,a.cpp文件(a编译单元)只要include "example.h",就可以在本编译单元使用变量x。b.cpp(b编译单元)也include "example.h",也可以在它的编译单元内使用变量x。使用的是各自版本的x,链接时彼此不冲突。
  extern:全局变量的声明,变量可以声明多次,不会报错。extern int x,本编译单元会操作一个变量x,但x的定义并不在此编译单元。所以编译时发现访问没有定义的变量x不会报错,在链接时会找到它的定义,多个编译单元共享一个全局变量。
所以,在.h文件中全局变量的定义,要么是static的,各编译单元用各自的。要么是extern的声明,我要用到一个全局变量,如果没找到定义就在别的编译单元内找找。如果在.h文件中定义一个变量,不合理。.h文件可能会被多个编译单元include,那链接时必然出现变量重定义。
      
链接过程将多个目标文件链接(依赖目标文件的3个表),组成完整二进制程序。此时可能的错误有:extern的变量却没有找到定义在哪;某个变量被多次定义。
 
以上就是C++源文件到可执行程序的处理过程,细节比这描述要复杂得多,但还是要先有骨再有肉。欢迎一起讨论。

C++生成二级制文件过程(预处理->编译->链接 )的更多相关文章

  1. C语言预处理编译链接各个阶段错误,分阶段的说一下

    C语言预处理编译链接各个阶段错误,分阶段的说一下 C语言预处理编译链接各个阶段错误,分阶段的说一下比如指针异常,数组下标越界什么的    我来答 1个回答 #热议# 你觉得这辈子有希望看到996消失 ...

  2. gitbook生成的_book文件本地打开后链接失效问题

    Gitbook 生成本地 html 的问题 在本地用 gitbook-cli根据 Summary 生成目录 然后在每个 md 文件里书写内容 然后用 gitbook serve .生成本地 html ...

  3. 【C编程基础】C编译链接命令gccc

    1.gcc安装 rpm -qa|grep gcc ==>检查gcc是否安装 gcc -v ==>检查gcc版本 yum -y install gcc ==>安装gcc  2.基本语法 ...

  4. 1.预处理,生成预编译文件(.文件): Gcc –E hello.c –o hello.i 2.编译,生成汇编代码(.s文件): Gcc –S hello.i –o hello.s 3.汇编,生成目标文件(.o文件): Gcc –c hello.s –o hello.o 4.链接,生成可执行文件: linux笔记

    1 动态查看日志 tail -f filename tail -1000f filename 2 解压当前目录内容为xxx.zip  zip -r xxx.zip ./* 3 查看内存使用情况 fre ...

  5. GCC编译器原理(三)------编译原理三:编译过程---预处理

    Gcc的编译流程分为了四个步骤: 预处理,生成预编译文件(.文件):gcc –E hello.c –o hello.i 编译,生成汇编代码(.s文件):gcc –S hello.i –o hello. ...

  6. 由动态库文件dll生成lib库文件(手动生成.def文件,然后使用lib命令编译,非常牛),同理可使用dll生成.a库文件

    本文基于OpenBlas的编译和安装,来说明如何从一个dll文件生成lib库文件. 参考OpenBlas的说明“Howto generate import library for MingW”,和Mi ...

  7. python3 pyinstaller生成exe文件过程问题解决记录

    1.使用pip安装pyinstaller 2.在cmd打开需生成可执行文件的python文件所在文件夹 3.使用命令pyinstaller -F -w **.py (代码中有import其他模块的,只 ...

  8. ROS知识(16)----如何编译时自动链接同一个工作空间的其他包的头文件(包含message,srv,action自动生成的头文件)

    catkin_make编译时,往往需要自动链接同一个工作空间的其他包的头文件.否则会出现类似如下的错误: /home/xx/xx_ws/srcA_package/src/db.hpp:13:26: f ...

  9. boost库生成文件命名和编译

    生成文件命名规则:boost中有许多库,有的库需要编译.而有的库不需要编译,只需包含头文件就可以使用.编译生成的文件名字普遍较长,同一个库根据编译链接选项不同,又可以生成多个不同名字的文件.生成的文件 ...

随机推荐

  1. Markdown示例

    欢迎使用 Cmd Markdown 编辑阅读器 我们理解您需要更便捷更高效的工具记录思想,整理笔记.知识,并将其中承载的价值传播给他人,Cmd Markdown 是我们给出的答案 -- 我们为记录思想 ...

  2. Cauchy 级数浓缩判别法

  3. HDU 4405 Aeroplane chess (概率DP)

    题意:你从0开始,要跳到 n 这个位置,如果当前位置是一个飞行点,那么可以跳过去,要不然就只能掷骰子,问你要掷的次数数学期望,到达或者超过n. 析:概率DP,dp[i] 表示从 i  这个位置到达 n ...

  4. PHP的高效IOC框架——CanoeDI

    一个非常简单且实用的IoC框架,相对于其他的Ioc框架有如下特点: 高效: 框架使用了非常实用且高效的算法,使得框架本身对应用的影响微乎其微,且框架提供了C扩展,最大限度的将性能提升到最高. 配置简单 ...

  5. Java Servlet与Web容器之间的关系

    自从计算机软件开发进入网络时代,就开始涉及到通讯问题.在客户/服务器(也叫C/S应用)时期,每个软件都有自己的客户端和服务器端软件.并且客户端和服务器端之间的通讯协议差别也很大.后来随着互联网的发展, ...

  6. datax+hadoop2.X兼容性调试

    以hdfsreader到hdfswriter为例进行说明: 1.datax的任务配置文件里需要指明使用的hadoop的配置文件,在datax+hadoop1.X的时候,可以直接使用hadoop1.X/ ...

  7. json中$ref对象重复引用问题

    FastJson提供了SerializerFeature.DisableCircularReferenceDetect这个序列化选项,用来关闭引用检测.关闭引用检测后,重复引用对象时就不会被$ref代 ...

  8. ios图片添加文字或者水印

    在项目中,我们会对图片做一些处理,但是我们要记住,一般在客户端做图片处理的数量不宜太多,因为受设备性能的限制,如果批量的处理图片,将会带来交互体验性上的一些问题.首先让我们来看看在图片上添加文字的方法 ...

  9. 重绘控件中OnPaint、OnDraw、OnDrawItem和DrawItem的区别

    ==================================================================================================== ...

  10. java获取路径的方法

    package com.zjf; import java.io.File; public class GetPath { public static void getPath() { //方式一 Sy ...