- 浏览: 140708 次
文章分类
最新评论
在开始之前,我们得先明确两个概念,即强符号和弱符号。
所谓强符号,就是指函数和已初始化的全局变量。自然弱符号就是指未初始化的全局变量。
在unix系统中,链接器采取以下规则来处理多重定义的全局符号:
1、同一个文件中不允许有多个相同强符号。
2、如果一个对象有一个强符号和多个弱符号,则选择强符号。
3、如有多个弱符号,则任选一个。
现在改说人话,稍微以例子解释一下各个规则。
1、多个强符号的情况:
此时若试图链接这两个文件,那么编译器将会报错,因为强符号x被定义了多次。
2、一个强符号的情况:
此时链接这两个文件输出为:x=2222。
3、无强符号的情况:
此时的输出同上例。
对于规则2和规则3,如果稍不注意就有可能出错,尤其是当重复的符号定义还有不同的类型时,如下示例:
此时的输出将是“出人意料”的:x=0, z=0 !!
为何会这样?因为全局符号x在两个文件中的类型不一样,而又以强符号为准,所以在第二个文件中的x引用的内存是第一个文件中的,不过因为其将x的int类型扩展成了double类型,而通常系统中double是8个字节,int是4个字节,所以会覆盖掉更后面的4个字节,因而顺带就更改了z的值!
所谓强符号,就是指函数和已初始化的全局变量。自然弱符号就是指未初始化的全局变量。
在unix系统中,链接器采取以下规则来处理多重定义的全局符号:
1、同一个文件中不允许有多个相同强符号。
2、如果一个对象有一个强符号和多个弱符号,则选择强符号。
3、如有多个弱符号,则任选一个。
现在改说人话,稍微以例子解释一下各个规则。
1、多个强符号的情况:
//main.c #include<stdio.h> void foo(); int x = 1513; //强符号 int main(void){ return 0; }
#include<stdio.h> int x = 2222; //强符号 void foo(){ ; }
此时若试图链接这两个文件,那么编译器将会报错,因为强符号x被定义了多次。
2、一个强符号的情况:
//main.c #include<stdio.h> void foo(); int x = 1513; //强符号 int main(void){ foo(); printf("x=%d\n", x); return 0; }
//foo.c #include<stdio.h> int x; //弱符号 void foo(){ x = 2222; }
此时链接这两个文件输出为:x=2222。
3、无强符号的情况:
//main.c #include<stdio.h> void foo(); int x; //弱符号 int main(void){ x = 1111; foo(); printf("x=%d\n", x); return 0; }
//foo.c #include<stdio.h> int x; //弱符号 void foo(){ x = 2222; }
此时的输出同上例。
对于规则2和规则3,如果稍不注意就有可能出错,尤其是当重复的符号定义还有不同的类型时,如下示例:
//main.c #include<stdio.h> void foo(); int x = 1513; //强符号,int类型 int z = 3333; //强符号 int main(void){ foo(); printf("x=%d, z=%d\n", x, z); return 0; }
//foo.c double x; //弱符号,double类型 void foo(){ x = 0.0; }
此时的输出将是“出人意料”的:x=0, z=0 !!
为何会这样?因为全局符号x在两个文件中的类型不一样,而又以强符号为准,所以在第二个文件中的x引用的内存是第一个文件中的,不过因为其将x的int类型扩展成了double类型,而通常系统中double是8个字节,int是4个字节,所以会覆盖掉更后面的4个字节,因而顺带就更改了z的值!
发表评论
-
浮点运算指令
2019-05-22 23:13 1565上一节介绍了浮点数与各种数值类型之间的相互转换 ... -
浮点数类型转换指令
2019-05-15 22:37 1684在浮点寄存 ... -
浮点寄存器概述
2019-05-14 22:31 2564本文介绍的浮点寄存器是基于 AVX2(Adva ... -
汇编指令之跳转指令
2019-04-15 00:21 4746正常执行的情况下,指令会按照顺序一条条地执行, ... -
汇编指令之条件码
2019-04-08 21:05 2334在系统底层,除了整数寄存器,CPU 还维护着一 ... -
汇编指令之算术和逻辑操作指令
2019-03-28 22:16 1333下表是 x86-64 ... -
汇编指令之数据传送指令
2019-03-25 21:28 1274在x86-64 中的 ... -
x86-64 中的寄存器与汇编操作数杂述
2019-03-20 21:45 981Intel 中常用 ... -
hello 程序执行背后的故事
2018-12-26 21:48 605源文件 hello. ... -
linux启动服务概述
2017-04-08 02:43 396传统的linux中定义了七个运行级,分别如下: ... -
unix限制
2017-04-04 16:08 571UNIX系统实现定义了很多幻数和常量,其中有很 ... -
linux引导加载程序--GRUB
2017-04-04 04:22 622linux世界里有两种 ... -
存储器映射
2016-06-13 00:12 548注:本文摘自《深入理解计算机操作系统》第九章--虚拟存 ... -
虚拟存储器对存储器管理的作用
2016-06-10 16:00 691注:本文中的大部分内容均是摘录自《深入理解计算机系统》一书,权 ... -
信号处理问题
2016-06-03 08:31 560注:本文摘自《深入理解计算机系统》第8章 --- 异常控制流。 ... -
僵尸进程
2016-05-23 23:57 357在解释僵尸进程的概念之前,我们得先了解这样的一个事实: 一个进 ... -
程序优化之存储器别名使用
2016-05-20 08:55 792说明:本文示例摘自《深入理解计算机系统》第五章----优化程序 ... -
条件变量基本概念与原理(转载)
2016-05-20 08:54 1559对于条件变量,我一直感到很困惑,搞不清其与互斥锁到底有啥区别, ... -
CPU与磁盘的交互过程
2016-05-19 09:05 1829对于计算机系统底层技术,想必很多人都和我一样不太了解,最近在学 ... -
存储器层次结构中基本的缓存原理
2016-05-19 09:00 660对于操作系统,我们知道,越靠近CPU的存储器,其存储速度就会越 ...
相关推荐
**知识点1:** Java摒弃了C++中的一些复杂特性,例如指针、结构和类型定义,不支持全局变量、预处理器(#include和#define),以及多重继承。相反,Java仅支持单继承,这简化了对象模型并提高了安全性。此外,Java的...
Ruby的标准库提供了丰富的功能,如网络通信、XML解析、数据库连接等,书中也会有相应介绍。 最后,对于新手来说,了解Ruby的开发环境和工具如RubyMine、RVM、Bundler和Gemfile也是必不可少的。这些工具帮助开发者...
那么额外的变量将在最后一个符号解析之 分配并接受行的保留文本。 usebackq - 指定新语法已在下类情况中使用: 在作为命令执行一个后引号的字符串并且 引号字符为文字字符串命令并允许在 fi 中使用双引号扩起文件...
- **解析**:在这个例子中,`modi()` 函数试图直接赋值 `img1 = img2`,但这只是创建了一个新的局部变量 `img1` 指向 `img2` 的引用,并不会改变全局变量 `img1` 的值。因此,调用 `displ()` 输出的仍然是 `[12, 34,...
- **定义**:类是对现实世界中一类事物的抽象,是对象的模板。 - **组成**:属性(成员变量)和行为(方法)。 #### 14. 对象 - **定义**:对象是类的一个实例。 - **使用场景**:当需要表示具体的事物或进行具体...
根据给定的北京航空航天大学831交通信息综合2021年考研专业课初试大纲,本篇文章将深入解析该大纲所涉及的关键知识点。这些知识点涵盖了四个主要方面:单片机原理及系统设计、C语言程序设计、自动控制原理以及交通...
以下是这些知识点的详细解析: ### 1. 指针与数组操作 在Objective-C中,指针与数组的结合使用是常见的场景。例如,`int a[5]={1,2,3,4,5}; int* ptr=(int*)(&a+1); printf("%d,%d",*(a+1),*(ptr-1));` 这段代码...
那么额外的变量将在最后一个符号解析之 分配并接受行的保留文本。 usebackq - 指定新语法已在下类情况中使用: 在作为命令执行一个后引号的字符串并且 引号字符为文字字符串命令并允许在 fi 中使用双引号扩起文件名称...
11.8.1 全局变量与局部变量 11.8.2 globa语句 11.8.3 作用域的数字 11.8.4 闭包 11.8.5 作用域和lambda 11.8.6 变量作用域和名称空间 11.9 *递归 11.10 生成器 11.10.1 ...
### 计算机二级等级考试知识点解析 #### 宏与模块 - **宏**:宏是一种特殊的数据库对象,它可以独立存在,并且能够执行一系列预定义的动作。宏的主要用途在于简化复杂的任务流程,使得用户可以通过简单的操作来触发...
- **IP 地址**: 每台连接到 Internet 的设备都需要一个唯一的 IP 地址以便进行通信。 ### 12. 变量与数组赋值 **知识点:** - **变量赋值**: 在编程语言中,变量可以被赋值。 - **数组赋值**: 数组的元素可以通过...
出处:风流的CG网络日志 时间:Mon, 28 Aug 2006 07:24:34 +0000 ...switch是对多重if-elseif-else结构的最好的替换: switch ($i) { case 0: print "i equals 0"; case 1: print "i equals 1"; case 2: print "i ...
模块或全局缺省控制器 7.12. MVC 异常 7.12.1. 介绍 7.12.2. 如何处理异常? 7.12.3. 可能遭遇的MVC异常 7.13. 从以前的版本移植 7.13.1. 从 1.0.x 到 1.5.0 或更新的版本的移植 7.13.2. 从 0.9.3 到 1.0.0RC...