C++程序文件链接

1.什么是转换单元
程序中的每个.cpp文件和它包含的所有头文件称为一个转换单元。
编译器处理每个转换单元,生成二进制对象文件,用扩展名.obj来标识。
链接器将对象文件组合起来,生成一个可执行文件,用扩展名.exe来标识。

2.作用域
使用{}来限定变量的作用域

内部作用域可以定义一个和外部作用域相同的名称,此时,内部作用域中定义的名称,将隐藏外部作用域中的名称,

若要访问外层作用域中的名称,可使用解析运算符::,解析运算符的介绍,可参考 C++范围解析运算符::的使用

int main()
{
const int limit =10;
std::cout<<"limit 1 is "<<limit<<std::endl;
{
const int limit = 5;
std::cout<<"limit 2 is "<<limit<<std::endl;
std::cout<<"limit 3 is "<<::limit<<std::endl;
}
std::cout<<"limit 4 is "<<limit<std::endl;
}

输出结果:
limit 1 is 10
limit 2 is 5
limit 3 is 10
limit 4 is 10

3.转换单元的全局名称属性linkage
每个转换单元中的全局名称,都有一个属性linkage,该属性指明该全局名称可以在程序代码的什么地方使用。
内部链接属性:该名称只能在同一转换单元的任何地方访问。比如全局const变量。
外部链接属性:该名称除了在同一转换单元访问外,还可在其他的转换单元中访问。除了全局const变量,其他的全局名称都是外部链接属性的。

局部名称没有链接属性。

4.什么是“一个定义”规则
在所有的转换单元中,外部链接属性的全局名称,如变量、函数、类类型、枚举类型、模板都只能定义一次。
内联函数除外,内联函数的定义必须出现在调用该函数的每个转换单元中。

内部链接属性的名称可以在多个转换单元中同时定义。

5.如何访问另一转换单元中定义的变量
对于函数来说,如果函数的调用和定义不在同一个转换单元,编译器会把这个函数调用标记为外部的,让链接程序去处理它。

对于变量来说,是不同的。必须使用extern关键字来声明该变量。表示该变量的定义在另一个转换单元中。

示例代码如下:

myextern.cpp
int limit = 15;

mymain.cpp
int main()
{
    extern int limit;
    std::cout<<"Extern limit is "<<limit<<std::endl;
    return 0;
}

由链接属性linkage的介绍,我们知道const变量是内部链接属性的,只能在转换单元内部访问。

而定义一个const变量,希望其他的转换单元都可以使用的情况是常见的,如圆周率PI,const double pi=3.14159265,

那么,怎么才能让const变量也具有外部链接属性呢。
我们只需要在定义const变量时,也加上extern关键字就可以了。

示例代码如下:

myextern.cpp
extern const double pi=3.14159265;

mymain.cpp
int main()
{
    extern const double pi;
    std::cout<<"Extern pi is "<<pi<<std::endl;
    return 0;
}

另外需要说明的是,extern变量声明的位置,决定了该外部变量的作用域。

参考资料:《C++入门经典 第三版》 pp.309-318

时间: 05-24

C++程序文件链接的相关文章

程序的链接和装入及Linux下动态链接的实现

http://www.ibm.com/developerworks/cn/linux/l-dynlink/ 程序的链接和装入及Linux下动态链接的实现 程序的链接和装入存在着多种方法,而如今最为流行的当属动态链接.动态装入方法.本文首先回顾了链接器和装入器的基本工作原理及这一技术的发展历史,然后通过实际的例子剖析了Linux系统下动态链接的实现.了解底层关键技术的实现细节对系统分析和设计人员无疑是必须的,尤其当我们在面对实时系统,需要对程序执行时的时空效率有着精确的度量和把握时,这种知识更显重

【深入理解计算机系统03】程序的链接

第三篇:程序的链接 > 链接器的由来 高级语言出现之后,需要多人开发不同模块. 链接步骤: 1) 确定符号引用关系 确定符号的定义 2) 合并相关.o文件 同一地址空间,安排虚拟地址空间 3) 确定每个符号的地址 4) 在指令中填入新的地址 使用链接的好处: 1. 模块化 2. 提高编译效率和节省内存空间(共享库的复用) 只需要重新编译被修改的源程序文件 > 目标文件格式 分类: 1. 可重定位目标文件:.O文件,地址和数据从0开始 2. 可执行目标文件:可以直接被复制到内存中执行.这里发生了

linux下c程序的链接、装载和库(3)

9. 目标文件放在一起-->静态库. 你的同事给出的目标文件太多了,从 one.o two.o …… …… 一直到 xxx.o. 好的,你如果真正想用,你的同事提供的这些现有的目标文件,你得做三件事: 一,查看自己的源文件,看看用到了哪些函数: 二,明确这些函数来自于哪个目标文件,本例中,很容易,因为函数的名字和目标文件的名字是对应的,比如one.o就会提供一个名称为one的函数: 三,使用 ld ,将你自己的目标文件和第二步中找到的那些目标文件链接起来,生成可执行文件. 第一步就是个很耗时的过

linux下c程序的链接、装载和库(1)

读完<程序员的自我修养--链接.装载和库>相关章节,想来总结一下,若有错误,请指正,多谢. 1. 什么叫目标文件? 你的工程里有很多xxx.c这样的源文件,这些文件是文本文件,只有人能够认识(当然编译器认识),但是,cpu可不认识.问题就是,真正执行指令的是cpu. 让编译器翻译一下(这里面有很多过程,这不是这篇文章的重点),一般来说,一个xxx.c文件就能翻译成一个xxx.o,这就是目标文件了. 一个源文件就对应一个目标文件,这个目标文件就存储了有关这个源文件的所有信息了,包括在这个源文件里

转载:ios程序编译链接参数 all_load 的 ld duplicate symbol _main 的 bug及修复

转载自:http://www.cnblogs.com/dabaopku/archive/2012/12/12/2813940.html ios程序编译链接参数 all_load 的 ld duplicate symbol _main 的 bug及修复 问题 -all_load 是在Objective-C 编译时常用到的一个参数,比如这篇文章所介绍的,生成静态库的一些问题-all_load.但是我们在加入这个参数后,有时会出现"ld: duplicate symbol _main"的错误

解决qt程序的链接阶段出现 undefined reference 错误

错误的原因是我使用到了 QT Widgets 模块中的东西,但是makefile的链接的参数中没有 widgets.其实官网上提到了这个: http://doc.qt.io/qt-5/qtwidgets-index.html 解决的方法是手动修改你的 .pro 文件,在里面添加下面这句: QT += widgets 如果出现类似的 undefined reference 这种错误应该也是在程序的链接阶段没有找到相应的函数或方法,解决方法也应该类似.

[转]c++应用程序文件的编译过程

原文地址 这里讲下C++文件的编译过程及其中模板的编译过程: 一:一般的C++应用程序的编译过程.    一般说来,C++应用程序的编译过程分为三个阶段.模板也是一样的. 在cpp文件中展开include文件. 将每个cpp文件编译为一个对应的obj文件. 连接obj文件成为一个exe文件(或者其它的库文件). 下面分别描述这几个阶段.1.include文件的展开.    include文件的展开是一个很简单的过程,只是将include文件包含的代码拷贝到包含该文件的cpp文件(或者其它头文件)

C#获取程序文件相关信息的方法

本文实例讲述了C#获取程序文件相关信息的方法,分享给大家供大家参考. 具体实现方法如下: using System.Reflection; using System.Runtime.CompilerServices; // // 有关程序集的常规信息是通过下列 // 属性集控制的.更改这些属性值可修改与程序集 // 关联的信息. // [assembly: AssemblyTitle("")] [assembly: AssemblyDescription("")]

应用程序如何链接静态QT Plugin库

错误描述静态编译了QT库后,我的应用程序要链接到这些静态库.但是出现了如图所示错误:运行时错误错误提示: This application failed to start because it could not find or load the Qt platform plugin "windows" in "". 解决过程Google关键字"Qt staticPlugins", to get the first result as: How