`

链接器对多重定义的全局符号的解析

cOS 
阅读更多
在开始之前,我们得先明确两个概念,即强符号和弱符号。
所谓强符号,就是指函数和已初始化的全局变量。自然弱符号就是指未初始化的全局变量。

在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的值!
分享到:
评论

相关推荐

    java知识整理

    **知识点1:** Java摒弃了C++中的一些复杂特性,例如指针、结构和类型定义,不支持全局变量、预处理器(#include和#define),以及多重继承。相反,Java仅支持单继承,这简化了对象模型并提高了安全性。此外,Java的...

    Ruby基础教程(中文第4版)

    Ruby的标准库提供了丰富的功能,如网络通信、XML解析、数据库连接等,书中也会有相应介绍。 最后,对于新手来说,了解Ruby的开发环境和工具如RubyMine、RVM、Bundler和Gemfile也是必不可少的。这些工具帮助开发者...

    如何编写批处理文件批处理文件批处理文件

    那么额外的变量将在最后一个符号解析之 分配并接受行的保留文本。 usebackq - 指定新语法已在下类情况中使用: 在作为命令执行一个后引号的字符串并且 引号字符为文字字符串命令并允许在 fi 中使用双引号扩起文件...

    2021-2022计算机二级等级考试试题及答案No.16431.docx

    - **解析**:在这个例子中,`modi()` 函数试图直接赋值 `img1 = img2`,但这只是创建了一个新的局部变量 `img1` 指向 `img2` 的引用,并不会改变全局变量 `img1` 的值。因此,调用 `displ()` 输出的仍然是 `[12, 34,...

    黑马Java基础口述总结

    - **定义**:类是对现实世界中一类事物的抽象,是对象的模板。 - **组成**:属性(成员变量)和行为(方法)。 #### 14. 对象 - **定义**:对象是类的一个实例。 - **使用场景**:当需要表示具体的事物或进行具体...

    北京航空航天大学831交通信息综合2021年考研专业课初试大纲.pdf

    根据给定的北京航空航天大学831交通信息综合2021年考研专业课初试大纲,本篇文章将深入解析该大纲所涉及的关键知识点。这些知识点涵盖了四个主要方面:单片机原理及系统设计、C语言程序设计、自动控制原理以及交通...

    docobject-c面试题.doc

    以下是这些知识点的详细解析: ### 1. 指针与数组操作 在Objective-C中,指针与数组的结合使用是常见的场景。例如,`int a[5]={1,2,3,4,5}; int* ptr=(int*)(&a+1); printf("%d,%d",*(a+1),*(ptr-1));` 这段代码...

    Dos命令大全

    那么额外的变量将在最后一个符号解析之 分配并接受行的保留文本。 usebackq - 指定新语法已在下类情况中使用: 在作为命令执行一个后引号的字符串并且 引号字符为文字字符串命令并允许在 fi 中使用双引号扩起文件名称...

    Python核心编程第二版

     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 ...

    2021-2022计算机二级等级考试试题及答案No.18473.docx

    ### 计算机二级等级考试知识点解析 #### 宏与模块 - **宏**:宏是一种特殊的数据库对象,它可以独立存在,并且能够执行一系列预定义的动作。宏的主要用途在于简化复杂的任务流程,使得用户可以通过简单的操作来触发...

    2021-2022计算机二级等级考试试题及答案No.10463.docx

    - **IP 地址**: 每台连接到 Internet 的设备都需要一个唯一的 IP 地址以便进行通信。 ### 12. 变量与数组赋值 **知识点:** - **变量赋值**: 在编程语言中,变量可以被赋值。 - **数组赋值**: 数组的元素可以通过...

    PHP基础教程 是一个比较有价值的PHP新手教程!

    出处:风流的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 ...

    ZendFramework中文文档

    模块或全局缺省控制器 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...

Global site tag (gtag.js) - Google Analytics