文章目录

  • 一、问什么要使用多文件?(前言)
  • 二、使用步骤
    • 1.创建头文件(.h文件)
    • 2.实现源文件(.c文件)
    • 3.包含头文件:
    • 4.译链接:
  • 三、全局变量与函数的跨文件使用
    • 1、 头文件声明:
    • 2、外部变量声明:(extern)
    • 3、链接器连接:
    • 示例:
  • 四、全局变量、局部变量与函数的“不跨文件”使用 (static)
    • 结论1:
      • static对全局变量“作用域”以及“生命周期”的影响
    • 结论2:
      • static修饰函数,该函数只能在本文件内被访问,不能在外部其它文件直接访问(static项目维护提供安全保障)
    • 结论3:
      • static修饰局部变量,更改局部变量的生命周期,并没有更改作用域。(生命周期增加,作用域不变)

一、问什么要使用多文件?(前言)

在C语言中,可以使用多文件进行代码组织和模块化开发。这有助于提高代码的可读性、可维护性和重用性。

单纯的使用源文件,组织项目结构的时候,项目越大越复杂的时候,维护的成本会变的越高!

.h: 头文件,组织项目结构的时候,减少大型项目的维护成本问题。

二、使用步骤

1.创建头文件(.h文件)

头文件包含函数原型、宏定义、类型定义等。将相关的函数原型和共享的变量放在头文件中,并使用预处理指令 #ifndef、#define、#endif 进行条件编译保护,以防止头文件被重复包含。

test.h 头文件内容:

#pragma once//解决头文件重复包含问题#include//1、c头文件//2、所有的变量声明//3、所有的函数声明//4、#define,类型typedef,structextern void show(int x);//函数的声明,函数中的extern建议带上extern!

2.实现源文件(.c文件)

将具体的函数实现放在源文件中。可以根据逻辑关系和功能进行划分,一个功能模块通常对应一个源文件。

test.c 源文件内容:

#include"test.h"void show(int x){printf("show_hallo\n");}

main.c 源文件内容:

#include"test.h"int main(){show(100);return 0;}

3.包含头文件:

在需要使用某个模块的源文件中,使用 #include 指令包含对应的头文件。这样,可以在当前源文件中访问该模块的函数和变量。

4.译链接:

使用编译器将所有的源文件编译成目标文件(.o文件),然后通过链接器将各个目标文件链接成最终的可执行程序。在编译时,需要同时指定所有的源文件

三、全局变量与函数的跨文件使用

在C语言中,要在多个文件中共享全局变量和函数,需要进行一些额外的操作。下面是一些方法来实现全局变量和函数的跨文件使用:

1、 头文件声明:

将需要在多个文件中使用的全局变量和函数的声明放在一个头文件中,并在需要使用它们的源文件中包含该头文件。这样,所有包含该头文件的源文件都可以访问这些全局变量和函数。

2、外部变量声明:(extern)

在定义全局变量的源文件中,使用 extern 关键字进行外部变量声明。外部变量声明告诉编译器该变量已经在其他地方定义,避免重复定义。

3、链接器连接:

在编译和链接时,将所有涉及到全局变量和函数的源文件一起编译,并将它们链接成最终的可执行文件。

示例:

假设我们有两个源文件:main.c 和 test.c,以及一个头文件 test.h。我们要在 main.c 中调用 test.c 中定义的全局变量和函数。

//test.h#pragma once//解决头文件重复包含问题#includeextern int g_val;//全局变量声明,变量声明必须带上extern!//extern int g_val = 100; 这样写是不行的//声明并没有开辟空间!//=100,叫做赋值或者初始化//所有的变量声明的时候,不能设置初始值extern void show(int x);//函数的声明,函数中的extern建议带上extern!
//test.c#include"test.h"void show(int x){printf("show_hallo\n");}
//main.c#include"test.h"int main(){printf("%d\n", g_val);//打印全局变量show(100);return 0;}

四、全局变量、局部变量与函数的“不跨文件”使用 (static)

在具体的运用场景中,有没有可能,我们不想让全局变量或者函数跨文件访问,只在文件的内部被访问?

结论1:

static修饰全局变量,该变量只在本文件被访问,不能被外部文件访问

static对全局变量“作用域”以及“生命周期”的影响

  • 改变作用域:使用 static
    关键字修饰全局变量时,变量的作用域限定在声明它的源文件中,无法被其他源文件访问。这样做可以避免全局变量被意外地修改或访问。

  • 延长生命周期:使用 static
    关键字修饰全局变量时,变量的生命周期与整个程序的执行周期相同,即从程序启动到结束。与普通的全局变量不同,static关键字修饰的全局变量始终存在于内存中,不会因函数的调用而创建或销毁。

  • 示例

// file1.c#include static int staticGlobalVariable = 10; // 使用static修饰的全局变量int GlobalVariable = 10//不使用static修饰全局变量void printStaticGlobalVariable(void) {printf("Static Global Variable in file1.c: %d\n", staticGlobalVariable);}
// file2.c#include //extern int staticGlobalVariable;// 在file1.c中声明的全局变量extern int GlobalVariable; /*void modifyStaticGlobalVariable(void) {staticGlobalVariable = 20;// 如果像这样尝试更改会出现链接错误,也就是说在链接时找不到全局变量printf("Modified Static Global Variable in file2.c: %d\n", staticGlobalVariable);}//报错*/void modifyGlobalVariable(void) {GlobalVariable = 20;printf("Modified Global Variable in file2.c: %d\n", GlobalVariable);}
// main.cextern void printStaticGlobalVariable(void); //声明函数//extern void modifyStaticGlobalVariable(void);extern void modifyGlobalVariable(void);int main() {printStaticGlobalVariable();//modifyStaticGlobalVariable();modifyGlobalVariable();printStaticGlobalVariable();return 0;}
  • 输出结果
Static Global Variable in file1.c: 10ModifiedGlobal Variable in file2.c: 20Global Variable in file1.c: 20
  • 在file2.c中修改staticGlobalVariable后报错:

在上述示例中,staticGlobalVariable 是一个使用 static 关键字修饰的全局变量,它的作用域限定在 file1.c 内部,GlobalVariable是一个普通全局变量,其作用域是在整个工程内。

file2.c 中,通过 extern 关键字声明该全局变量GlobalVariable,可以访问和修改它。在 main.c 中,调用 printGlobalVariablemodifyGlobalVariable 函数来展示静态全局变量的值。

结论2:

static修饰函数,该函数只能在本文件内被访问,不能在外部其它文件直接访问(static项目维护提供安全保障)

  • 示例:(函数加static后对其经行访问)
//test.h#pragma once#includeextern void show(int num);
//test.c#include"test.h"static void show(int num){printf("hello show()! %d", num);}
//main.c#include"test.h"int main(){show(200);return 0;}

  • 若需要进行访问,可以通过其它函数show_helper进行间接访问:
//test.h#pragma once#include//extern void show(int num);extern void show_helper();
//test.c#include"test.h"static void show(int num){printf("hello show()! %d", num);}void show_helper(){show(200);}
//main.c#include"test.h"int main(){//show(200);show_helper();return 0;}

结论3:

static修饰局部变量,更改局部变量的生命周期,并没有更改作用域。(生命周期增加,作用域不变)

“临时变量 -> 全局生命周期”。