首页 > 编程语言 >关于extern和模块化编程全局变量、函数、对象不同源文件之间的使用说明

关于extern和模块化编程全局变量、函数、对象不同源文件之间的使用说明

时间:2024-02-14 16:44:56浏览次数:30  
标签:常量 int 源文件 extern 全局变量 定义

extern的使用

在C语言中,extern关键字用于在多个源文件之间声明全局变量、函数或对象,实现模块间的交互和数据共享。即告诉编译器该变量或函数是在其他源文件中定义的,并且可以在当前源文件中使用。而局部函数的作用域限定在其定义所在的作用域内,无法被其他源文件直接访问或调用。因此,extern关键字不能用于共享局部函数。

对于变量

下面是一个使用extern共享全局变量的示例:
main.c

#include <stdio.h>

extern globalVar;  // 声明全局变量
//等同extern int globalVar;  



int main() {
    globalVar = 42;  // 在其他模块中修改全局变量的值
    printf("Global variable: %d\n", globalVar);
    return 0;
}

 other.c

int globalVar = 10;  // 定义全局变量

void printMessage() {
    printf("Hello, extern!\n");
}

在这个示例中,main.c中使用extern声明了一个全局变量globalVar,该全局变量在other.c中定义。main.c可以通过extern声明来访问和使用globalVar的值。
注意,在编译时,需要将main.cother.c都包含在编译过程中,以便正确链接和使用extern声明的全局变量或函数。

对于函数

 下面是一个使用extern共享全局函数的示例:
module1.c

void sharedFunction()  // 在module1.c中定义共享函数
{
  /*-------------*/  
}

module2.c

extern sharedFunction();  // 在module2.c中使用extern声明共享函数
//等同extern void sharedFunction();  
int main() {
    sharedFunction();  // 可以在其他模块中调用共享函数
    return 0;
}

宏定义常量和const常量区别

预处理

预处理是编译过程的一个阶段,在源代码被编译之前进行。在预处理阶段,预处理器会根据预处理指令处理源代码,包括宏替换、条件编译等。

预处理头文件

文件包含是 C 预处理程序的另一个重要功能。文件包含命令的一般形式为

#include"文件名" 或 #include<文件名> 

文件包含命令的功能是把指定的文件插入谈该命令行位置取代该命令行,从而把指定的文件和当前的源程序文件连成一个源文件。因为有些公用的符号常量或宏定义等可单单独组成一个文件,在其他文件的开头用包含命令包含该文件即可使用。这样,可避免在每 个文件开头都去书写那些公用量,从而节省时 间,并减少出错。

宏定义

宏定义就是在预处理阶段被展开成它们的值,并在编译时被硬编码到每个使用它们的地方,其作用域为宏定义命令起到源程序结束。这意味着它们的值在编译时是固定的,不存在需要共享的定义,所以 使用extern关键字进行共享宏定义是不必要的。另外,宏定义其值是不可修改的。

宏定义的常量没有类型,它是在编译前即预编译阶段进行字符替换,用#define定义,如下:

#define Pi 3.1415926

const常量

const定义常量则是由编译器在编译时处理的,而不是在预处理阶段。编译器会在编译过程中对常量进行处理,并将它们的值硬编码到生成的目标代码中。它是在运行时进行替换,其值在运行期间恒定不变,并且在编译时会进行严格的类型检验,同时系统也会为常量分配内存const关键字用于声明只读的常量,一旦被赋值,其值就不能再被改变,但是如果非要修改我们可以使用指针来修改其值。常量使用关键字const定义,如下:

const float PI = 3.14159;

C++语言可以用const 来定义常量,也可以用#define来定义宏常量。但是两者的区别在于:

1. const 常量在运行时进行替换,宏常量则是在预编译截断进行替换

2. const 常量有数据类型,而宏常量没有数据类型;

const和宏定义的应用

如果需要在不同的源文件中共享const常量的值(宏定义也是),可以将常量的定义放在一个头文件中,并在需要使用它的源文件中包含该头文件。这样可以确保不同的源文件使用的是相同的常量值。我们通常使用引用其头文件的方法,例如:

constants.h

#define PI 3.14159  // 在constants.h中定义常量或宏

extern const int MAX_SIZE;  // 使用extern声明共享常量

int add(int a, int b);    //函数的声明

constants.c

#include "constants.h"

const int maxNum = 100;  // 在constants.c中定义共享常量

int add(int a, int b) {
    return a + b;
}

main.c

#include <stdio.h>
#include "constants.h"
int totalNum;
int main() {
    printf("Max value: %d\n", PI); // 可以在其他模块中使用共享常量或宏
    printf("Max size: %d\n", maxNum); // 可以在其他模块中使用共享常量或宏
    totalNum=add(PI+maxNum);    //引用共享函数
    return 0;
}

/* ------------------------------分 隔 符------------------------------*/

对于全局变量,如果在对应的.h文件声明了,我们在其他源文件中如果要引用该变量,可以直接引用其头文件,然后直接使用。例如:

module1.h

extern int globalVar;     // 声明全局变量

int add(int a, int b);    //函数的声明

module1.c

#include "module1.h"

int globalVar = 42;       // 定义全局变量

int add(int a, int b) {
    return a + b;
}

module2.c

#include "module1.h"

int globalVar = 42;      // 定义全局变量

使用头文件的好处是,可以将共享的声明集中在一个地方,并在需要的源文件中引用,提高代码的可读性和可维护性。此外,头文件还可以包含其他模块所需的函数原型、结构体定义、宏定义等,方便模块之间的交互和共享。

总结来说,虽然在使用extern声明其他源文件的全局变量时并不一定需要引入头文件,但为了确保声明的一致性和代码的可维护性,通常建议使用头文件来声明和定义共享的实体。

 

 

 

 

标签:常量,int,源文件,extern,全局变量,定义
From: https://www.cnblogs.com/YYZYCS/p/18014310

相关文章

  • 第22天:安全开发-PHP应用&留言板功能&超全局变量&数据库操作&第三方插件引用
    #数据库操作-mysqli函数&增删改查PHP函数:连接,选择,执行,结果,关闭等参考:https://www.runoob.com/php/php-ref-mysqli.html常用:mysqli_connect()打开一个到MySQL的新的连接。mysqli_select_db()更改连接的默认数据库。mysqli_query()执行某个针对数据库的查询。mysqli_fetch......
  • Windows Server 2012无法安装 .NET3.5-安装角色或功能失败,找不到源文件
     最近在部署项目的是否需要安装sqlserver2008r2,前提条件,服务器需要安装.netframework3.5 服务器环境是windowsserver2012r2,然后;net3.5安装正常流程安装,一直装不上,网上有很多方法,但都解决不了,后面还是一个博主提到了阿里云,然后找到了解决方案,太难了 目前已安装补丁......
  • 添加代码运行登录注册页,并为其添加一些样式,和调用资源文件
    使用PyQt5(PySide2)+SQLAlchemy做一个登录注册页(二)本文将介绍自己用PyQt5+SQLAlchemy做的一个登录注册页,使用邮箱接收验证码,本文介绍是前后端未分离的实现方式,后续将出一个前后端分离的,你可以将PyQt5改为PySide2以获得更宽松的开源协议本文由于涉及到的代码较多,将会是一......
  • WebAssembly入门笔记[4]:利用Global传递全局变量
    利用WebAssembly的导入导出功能可以灵活地实现宿主JavaScript程序与加载的单个wasm模块之间的交互,那么如何在宿主程序与多个wasm之间传递和共享数据呢?这就需要使用到Global这个重要的对象了。一、数值类型全局变量二、将JavaScript函数设置为全局变量三、利用全局变量处理字符......
  • 复制资源文件(/Resources/Raw/)-文件处理
    c///<summary>///复制资源文件(/Resources/Raw/)///</summary>///<paramname="resourceFileName">资源文件名</param>publicasyncstaticTaskCopyFileFromResource(stringresourceFileName){//FileSystem.Current.AppDataDirecto......
  • rust使用lazy_static对全局变量多线程并发读写示例
    首先需要在项目依赖Cargo.toml添加lazy_static依赖项[dependencies]lazy_static="1.4.0"示例代码如下:uselazy_static::lazy_static;usestd::sync::{RwLock,RwLockReadGuard,RwLockWriteGuard};usestd::thread;#[derive(Debug)]structSharedData{data:Vec<......
  • 第 3 章:将源文件转换为抽象语法树
    如前一章所学,编译器通常分为前端和后端两部分。在本章中,我们将实现一种编程语言的前端,即主要处理源语言的部分。我们将学习现实世界中编译器使用的技术,并将其应用于我们的编程语言。我们的旅程将从定义我们的编程语言的语法开始,结束于抽象语法树(AST),它将成为代码生成的基础。你可......
  • C++ const 全局变量跨文件引用,无法解析的外部符号?
    前两天群里有人问了这样一个问题:在a文件中定义了一个全局变量,可以在b文件中引用。但一旦把全局变量改为const之后,就无法在b文件中引用,编译(链接)报错“无法解析的外部符号”,这是为什么?这是因为const修饰的变量默认具有文件作用域,如果想和非const变量一样具有全局作......
  • JavaScript保留字和预定义的全局变量及函数汇总
    保留字也称关键字,每种语言中都有该语言本身规定的一些关键字,这些关键字都是该语言的语法实现基础,JavaScript中规定了一些标识符作为现行版本的关键字或者将来版本中可能会用到的关键字,所以当我们定义标识符时就不能使用这些关键字了,下面介绍下JavaScript保留字和预定义的全局变量......
  • 让cp 产生的文件和源文件 时间戳相同
     要让 cp 命令产生的文件与源文件的时间戳相同,可以使用 -p选项。这个选项会保留文件的权限、所有者以及时间戳信息。以下是一个示例:cp-psourcefiledestinationfile在这个命令中,sourcefile 是源文件的名称,destinationfile 是目标文件的名称。通过使用 -p 选项,destin......