C语言详细分析讲解多文件的程序设计

目录
  • 一、多文件与编译器链接
  • 二、多文件之间的相互访问
  • 三、关于#include
  • 四、头文件使用的一些原则
  • 五、再论全局变量
  • 六、注意事项
  • 七、实验程序
  • 八、小结

一、多文件与编译器链接

如下图所示,.o 为目标文件,链接器将不同的目标文件装配组合在一起形成一个可执行文件。

二、多文件之间的相互访问

每个文件可以定义功能接口(可被其它文件访问的函数或数据)

  • 源文件:代码实现文件,后缀为.c
  • 头文件:源文件的接口定义文件,后缀为.h

当需要使用其它文件提供的功能时,包含对应的头文件

语法:

#include <hearer.h>

#include "header.h"

三、关于#include

#include 用于声明使用其它文件的功能(头文件可看作工具包)

#include <...>

在编译系统文件中查找头文件

#include "..."

先查找当前工程文件夹,再查找编译统文件夹

四、头文件使用的一些原则

  • 头文件中只做函数声明和变量声明(不做具体定义)
  • 头文件中可定义数据类型(typedef, struct, union, enum)
  • 根据具体实现,一个头文件可对应多个源文件(多数情况一对一)
  • 不要使用#include语句包含源文件

五、再论全局变量

普通全局变量

  • 源文件中定义的全局变量可在所有其它源文件中使用
  • 可使用 extern 关键字在头文件中进行声明,并在其它文件使用

静态全局变量

  • static 修饰的全局变量只能在当前源文件中使用
  • 无法通过 extern 关键字声明,在其它文件使用

六、注意事项

函数声明语句默认自带 extern 关键字修饰

类型定义必须在头文件中,仅类型声明无法创建变量

静态全局变量

  • 生命期为程序运行期
  • 作用域仅在定义的文件中
  • 无法直接在其它文件中使用

static 关键字可使函数具备文件作用域(静态函数)

静态函数无法在其它文件中被调用

函数设计时需要考虑是否在其它文件中使用

七、实验程序

以CodeBlcoks为例,先建好 main.c 文件之后,点击File,New,再点击File,选择 Empty file,分别建一个 .h 和 .c 文件,完成多文件创建。

opm.h 代码:

struct Test
{
    int a;
    int b;
};
extern int g_var;   // 声明全局变量时,不需要给出初始值
extern int f_var;
int add(int a, int b);
int mul(int, int);   // 进行函数声明的时候,可以省略参数名
extern void test();

opm.c 代码:

#include <stdio.h>
int g_var = 1;
static int f_var = 2;   // 只能在当前文件中使用 ==> 静态全局变量
static void func()  // 静态函数只能在当前文件中被调用
{
    printf("void func() : f_var = %d\n", f_var);
}
void test()   // 当前文件中定义的所有函数都可以调用 func() 函数
{
    func();
}
int add(int a, int b)
{
    return a + b;
}
int mul(int a, int b)
{
    return a * b;
}

main.c 代码:

#include <stdio.h>
#include <string.h>
#include "opm.h"
int main()
{
    struct Test t = {1, 2};
    printf("a + b = %d\n", add(t.a, t.b));
    printf("a * b = %d\n", mul(t.a, t.b));
    printf("g_var = %d\n", g_var);
    // printf("f_var = %d\n", f_var);   // 无法直接使用其他文件中定义的静态全局变量
    test();
    return 0;
}

下面为输出结果:

通过这个多文件程序,说明一个问题:

static 修饰的全局变量和函数只能在当前源文件中使用,所以 func() 函数不能再 main 函数中调用,而 test() 函数可以在 main 函数中被调用。

八、小结

  • 实际工程开发中,多文件程序设计是常态
  • 源文件实现具体功能,头文件声明接口
  • #include 用于声明需要使用其它文件中定义的功能
  • extern关键字用于函数和全局变量的声明
  • static 关键字修饰的全局变量不能在其它文件中使用

到此这篇关于C语言详细分析讲解多文件的程序设计的文章就介绍到这了,更多相关C语言 多文件程序设计内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • c语言程序设计文件操作方法示例(CreateFile和fopen)

    实例: (1)第一种方法CreateFile 复制代码 代码如下: #include "stdafx.h"#include <windows.h>void main(int argc, char* argv[]){      HANDLE hDevice = CreateFile("C://S.txt",            GENERIC_READ|GENERIC_WRITE,            0,            NULL,      

  • C语言详细分析讲解多文件的程序设计

    目录 一.多文件与编译器链接 二.多文件之间的相互访问 三.关于#include 四.头文件使用的一些原则 五.再论全局变量 六.注意事项 七.实验程序 八.小结 一.多文件与编译器链接 如下图所示,.o 为目标文件,链接器将不同的目标文件装配组合在一起形成一个可执行文件. 二.多文件之间的相互访问 每个文件可以定义功能接口(可被其它文件访问的函数或数据) 源文件:代码实现文件,后缀为.c 头文件:源文件的接口定义文件,后缀为.h 当需要使用其它文件提供的功能时,包含对应的头文件 语法: #in

  • C语言详细分析讲解struct与union使用方法

    目录 一.struct 的小秘密 二.结构体与柔性数组 三.C语言中的 union 四.小结 一.struct 的小秘密 C语言中的 struct 可以看作变量的集合 struct 的问题:空结构体占用多大内存?下面编写程序看一下吧: #include <stdio.h> struct TS { }; int main() { struct TS t1; struct TS t2; printf("sizeof(struct TS) = %d\n", sizeof(stru

  • C语言详细分析讲解关键字enum与sizeof及typedef的用法

    目录 一.枚举类型的使用方法 二.sizeof 关键字的用法 三.typedef 的意义 四.小结 一.枚举类型的使用方法 enum 是 C 语言中的一种自定义类型 enum 值是可以根据需要自定义的整型值 第一个定义的 enum 值默认为 0 默认情况下的 enum 值是在前一个定义值的基础上加 1 enum 类型的变量只能取定义时的离散值 enum 中定义的值是C语言中真正意义上的常量 在工程中 enum 多用于定义整型常量 下面看一段 enum 的使用代码吧: #include<stdio

  • C语言详细分析讲解关键字const与volatile的用法

    目录 一.const 只读变量 二.const 全局变量的分歧 三.const 的本质 四.const 修饰函数参数和返回值 五.volatile 解析 六.小结 一.const 只读变量 const 修饰的变量是只读的,本质还是变量 const 修饰的局部变量在栈上分配空间 const 修饰的全局变量在全局数据区分配空间 const 只在编译期有用,在运行期无用 const 修饰的变量不是真的常量,它只是告诉编译器该变量不能出现在赋值符号的左边. 二.const 全局变量的分歧 在现代C语言编

  • C语言详细分析讲解关键字goto与void的作用

    目录 一.关于goto 二.void 的意义 三.小结 一.关于goto 高手潜规则:禁用 goto 项目经验:程序质量与 goto 的出现次数成反比 最后的判决:将 goto 打入冷宫 下面看一段 goto 副作用分析的代码: #include <stdio.h> #include <malloc.h> void func(int n) { int* p = NULL; if( n < 0 ) { goto STATUS; } p = (int*)malloc(sizeof

  • C语言详细分析讲解流程控制语句用法

    目录 一.分支语句 1.if语句 2.switch语句 二.循环语句 1.for语句 2.break和continue语句 3.循环嵌套 4.while和do…while语句 一.分支语句 1.if语句 流程控制语句可以让程序中的语句不再从上到下逐条执行 分支是一种流程控制语句,可以把程序中某些语句忽略掉不去执行 if关键字可以用来编写分支语句,只有当表达式为真时,才会执行对应语句 如果多个分支的逻辑表达式之间存在互斥关系,则可以采用else关键字把他们合并成一个分支语句 一个分支语句中的多个逻

  • C语言详细分析讲解内存管理malloc realloc free calloc函数的使用

    目录 C语言内存管理 一.动态空间申请 二.动态空间的扩容 三.释放内存 C语言内存管理 malloc && realloc && free && calloc c语言中为了进行动态内存管理,<stdlib.h>中提供了几个函数帮助进行内存管理. 我们知道,C语言中是没有C++中的容器或者说是python中list,set这些高级的数据结构的,我们一旦申请了一段内存空间以后这一段空间就归你了,比如我们举个例子,我们申请一个数组 int nums[

  • C++详细分析讲解函数参数的扩展

    目录 一.函数参数的默认值 二.函数占位参数 三.小结 一.函数参数的默认值 C++ 中可以在函数声明时为参数提供一个默认值 当函数调用时没有提供参数的值,则使用默认值 参数的默认值必须在函数声明中指定 下面看一段代码: #include <stdio.h> int mul(int x = 0); int main(int argc, char *argv[]) { printf("%d\n", mul()); printf("%d\n", mul(-1

  • C语言详细i讲解qsort函数的使用

    目录 qsort 1.int型 2.float型 3.struct型 qsort 功能:Performs a quick sort.(快速排序) 参数:void qsort( void *base, size_t num, size_t width, int (*cmp )(const void *e1, const void *e2 ) ); 头文件:#include <stdlib.h> 用法: 第一个参数待排数组的首元素地址 第二个参数待排数据个数 第三个待排数据中每个参数的大小——单位

  • Java详细分析讲解泛型

    目录 1.泛型概念 2.泛型的使用 2.1泛型类语法 2.2泛型方法语法 2.3泛型接口语法 2.4泛型在main方法中的使用 3.擦除机制 4.泛型的上界 5.通配符 5.1通配符的上界 5.2通配符的下界 6.包装类 6.1装箱和拆箱 1.泛型概念 泛型就是将类型参数化 所谓类型参数化就是将类型定义成参数的形式,然后在使用此类型的时候的时候再传入具体的类型 到这我们可以看出来:泛型在定义的时候是不知道具体类型的,需要在使用的时候传入具体的类型,泛型可以用在类.接口和方法中,这样做的好处是一个

随机推荐