C语言--连接器

2024-05-01 13:18
文章标签 语言 连接器

本文主要是介绍C语言--连接器,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

连接

概述

一个 C 程序可能是由多个分别编译的部分组成,这些不同部分通过一个通常叫做连接器的程序合并成一个整体。

什么是连接器

C 语言中的一个重要思想就是分别编译,即若干个源程序可以在不同的时候单独进行编译,然后在恰当的时候整合在一起。但是连接器一般是与 C 编译器分离的,它不可能了解 C 语言的诸多细节。尽管连接器并不理解 C 语言,然而它却能够理解机器语言和内存布局。编译器的责任就是把 C 源程序 翻译 成对连接器有意义的形式,这样连接器就能够 读懂 C 源程序了。

典型的连接器把由编译器或汇编器生成的若干个目标模块,整合成一个被称为载入模块或可执行文件的实体,该实体能够被操作系统直接执行。其中,目标模块是直接作为输入提供给连接器的;而另外一些目标模块则是根据连接过程的需要,从包括类似 printf 函数的库文件中取得的。

连接器的输入时一组目标模块和库文件,连接器的输出时一个载入模块。连接器读入目标模块和库文件,同时生成载入模块。对每个目标模块中的每个外部对象,连机器都要检查载入模块,看是否已有同名的外部对象。如果没有,连接器就将该外部对象添加到载入模块中;如果有,连接器就要开始处理命名冲突。

声明与定义

这是定义

int a;

这是声明

extern int a;

每个外部变量之定义一次

命名冲突与 static 修饰符

两个具有相同名称的外部对象实际上代表的是同一个对象,即使编程者的本意并非如此,但系统却会如此处理,static 修饰符是一个能够减少此类命名冲突的有用工具。

static 修饰符不仅适用于变量,也适用于函数。

检查外部类型

假定有一个 C 程序,它由两个源文件组成。一个文件中包含外部变量 a 的声明

extern int n;

另一个文件中包含外部变量 n 的定义

long n;

假定两个语句都不在任何一个函数体内,因此 c 是外部变量。
这是一个无效的 C 程序,因为同一个外部变量在两个不同的文件中被声明为不同的类型,因此,保证一个特定名称的所有外部定义在每个目标模块中都有相同的类型,一般来说是程序猿的责任,而且,相同的类型 应该是严格意义上的相同。例如下面的程序

在一个文件中包含定义:

char filename[] = "hello tyustli";

在另一个文件中包含声明:

extern char *filename;

在第一个文件中 filename 是一个字符数组的名称,而不是字符指针,在第二个文件中 filename 是一个指针,这两个对 filename 的声明使用存储空间的方式是不同的,他们无法以一种合乎情理的方式共存。
要更正上例改法如下:

char filename[] = "hello world"; /* 文件1 */
extern char filename[];          /* 文件2 */

或者:

char *filename = "hello world"; /* 文件1 */
extern char *filename;          /* 文件2 */

关于外部类型,C 语言规则是如果一个未声明的标识符后跟一个开括号,那么它将被视为一个返回整型的函数。

头文件

file.h 中包含声明

extern char filename[];

需要用到外部变量 filename 的每个 C 源文件都应该加上这样一个语句:

#include "file.h"

最后在一个源文件 file.c 中,给出 filename 的初始值

#include "file.h"
char filename[] = "hello world";

特别需要指出的是,定义该外部对象的模块也应该包含这个头文件。

这篇关于C语言--连接器的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/951790

相关文章

C语言中%zu的用法解读

《C语言中%zu的用法解读》size_t是无符号整数类型,用于表示对象大小或内存操作结果,%zu是C99标准中专为size_t设计的printf占位符,避免因类型不匹配导致错误,使用%u或%d可能引发... 目录size_t 类型与 %zu 占位符%zu 的用途替代占位符的风险兼容性说明其他相关占位符验证示

C语言进阶(预处理命令详解)

《C语言进阶(预处理命令详解)》文章讲解了宏定义规范、头文件包含方式及条件编译应用,强调带参宏需加括号避免计算错误,头文件应声明函数原型以便主函数调用,条件编译通过宏定义控制代码编译,适用于测试与模块... 目录1.宏定义1.1不带参宏1.2带参宏2.头文件的包含2.1头文件中的内容2.2工程结构3.条件编

Go语言并发之通知退出机制的实现

《Go语言并发之通知退出机制的实现》本文主要介绍了Go语言并发之通知退出机制的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录1、通知退出机制1.1 进程/main函数退出1.2 通过channel退出1.3 通过cont

Go语言编译环境设置教程

《Go语言编译环境设置教程》Go语言支持高并发(goroutine)、自动垃圾回收,编译为跨平台二进制文件,云原生兼容且社区活跃,开发便捷,内置测试与vet工具辅助检测错误,依赖模块化管理,提升开发效... 目录Go语言优势下载 Go  配置编译环境配置 GOPROXYIDE 设置(VS Code)一些基本

深入理解Go语言中二维切片的使用

《深入理解Go语言中二维切片的使用》本文深入讲解了Go语言中二维切片的概念与应用,用于表示矩阵、表格等二维数据结构,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习吧... 目录引言二维切片的基本概念定义创建二维切片二维切片的操作访问元素修改元素遍历二维切片二维切片的动态调整追加行动态

Go语言中make和new的区别及说明

《Go语言中make和new的区别及说明》:本文主要介绍Go语言中make和new的区别及说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1 概述2 new 函数2.1 功能2.2 语法2.3 初始化案例3 make 函数3.1 功能3.2 语法3.3 初始化

Go语言中nil判断的注意事项(最新推荐)

《Go语言中nil判断的注意事项(最新推荐)》本文给大家介绍Go语言中nil判断的注意事项,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录1.接口变量的特殊行为2.nil的合法类型3.nil值的实用行为4.自定义类型与nil5.反射判断nil6.函数返回的

Go语言数据库编程GORM 的基本使用详解

《Go语言数据库编程GORM的基本使用详解》GORM是Go语言流行的ORM框架,封装database/sql,支持自动迁移、关联、事务等,提供CRUD、条件查询、钩子函数、日志等功能,简化数据库操作... 目录一、安装与初始化1. 安装 GORM 及数据库驱动2. 建立数据库连接二、定义模型结构体三、自动迁

Go语言代码格式化的技巧分享

《Go语言代码格式化的技巧分享》在Go语言的开发过程中,代码格式化是一个看似细微却至关重要的环节,良好的代码格式化不仅能提升代码的可读性,还能促进团队协作,减少因代码风格差异引发的问题,Go在代码格式... 目录一、Go 语言代码格式化的重要性二、Go 语言代码格式化工具:gofmt 与 go fmt(一)

Go语言中泄漏缓冲区的问题解决

《Go语言中泄漏缓冲区的问题解决》缓冲区是一种常见的数据结构,常被用于在不同的并发单元之间传递数据,然而,若缓冲区使用不当,就可能引发泄漏缓冲区问题,本文就来介绍一下问题的解决,感兴趣的可以了解一下... 目录引言泄漏缓冲区的基本概念代码示例:泄漏缓冲区的产生项目场景:Web 服务器中的请求缓冲场景描述代码