c语言模块化编程思想(一)

前言

提示:这里可以添加本文要记录的大概内容:
任何一个软件项目都可以被划分为不同的模块,然后分给不同的人去完成。模块化编程不仅可以由多人协作,分工实现,而且还可以让我们的软件系统结构清晰,层次更加分明,更加易于管理和维护。 这便是c语言模块化编程思想的由来


提示:以下是本篇文章正文内容,下面案例可供参考

模块的编译和链接

在一个C语言软件项目中,整个软件系统可以被划分为不同的模块,然后交给不同的人去完成。这项任务将产生一下几个问题:

  • 每个人在实现各自模块的过程中注意什么?
  • 如何协作
  • 模块如何集成到系统中去?(makefile项目管理软件)

一个C语言项目通常分为不同的模块,通常由多个文件来实现。在项目编译的过程中,编译器是以C源文件为单位进行编译的,每一个C源文件都会被编译器翻译成一个对应的目标文件。接下来链接器对每一个目标文件进行解析,将文件中的代码段,数据段分别组装,生成一个可执行的目标文件。如果程序调用了库函数,则链接器也会找到对应的库文件,将程序中的库代码一同链接到可执行文件中。

编译链接过程
需要注意:在链接过程中,如果多个目标文件定义了重名的函数或全局变量,就会发生符号冲突,出现重定义错误。此时链接器就要对这些重复定义的符号做符号决议( 符号决议有一定的规则 )。

在一个大型项目中,可以通过控制参数来控制编译的流程:预处理,编译,汇编,链接,指定多个文件的编译顺序。但是当文件特别多时,通过使用命令行的方式来完成整个项目的编译就会特别麻烦。工程上,通常使用自动化编译工具make来编译项目,make自动编译工具依赖项目的Makefile文件。Makefile文件主要作用用来小数各个模块之间的依赖关系,生成的可执行文件,如何编译,先编译哪个,后编译哪个,Makefile都有表述。(现代工程一般使用Cmake工具)

系统模块划分

系统模块划分法

理清楚:

  • 什么是系统
  • 什么是模块

系统就是各种对象相互关联,相互作用形成的具有特定功能的有机整体。这些对象可以看作不同的模块。模块与模块之间是相互作用,相互关联的。系统的模块化设计就是将系统目标按模块化方式分解,设计,实现,集成。模块是模块化的产物,每一个模块都是具有特定功能的有机组成。

系统和模块的先后顺序:先有系统,有了系统目标和功能定义,然后才有模块划分,最后才有模块的实现。系统的外在功能是通过系统内多个模块之间相互作用,相互关联实现的。

如何对一个系统进行模块化划分:

  • 确定系统的功能或目标(知道自己要做什么,实现什么功能和目标)

  • 根据系统的功能和目标,设计出一组系统工作流程

  • 根据这个工作流程,确定角色和分工,各个角色之间如何交互,如何关联。

  • 角色确定后,就可以根据各个角色将系统划分成不同的模块

在实际的工程项目中,在对一个系统进行功能分析,模块划分的时候,也要根据项目的工作量,团队人数,团队员工水平等因素进行合理的划分。假如设计一个MP3播放器,支持音乐播放和录音功能。

  • 系统目标:播放音乐,录音

  • 基本工作流1:从磁盘读取MP3文件 > 解码 > 声卡 > 显示

  • 流2:麦克风录音,AD转换 > 内存 > 声音编码 > 存入磁盘

  • 角色:存储,显卡,声卡,麦克风,编解码器

  • 模块:存储模块,显示模块,编解码模块

在这里插入图片描述

当系统比较复杂时,或者由于模块划分的比较多导致模块过多时,需要考虑进一步的分层。可以按照模块间的依赖关系,将一个系统划分为不同的层。

例如:MP3系统升级了,移植了OS,添加了文件系统模块,增加了绚丽的GUI界面。文件系统对存储模块的读写进行抽象,应用程序可以通过文件系统的read/write接口直接读写MP3歌曲文件。MP3播放界面,可以通过GUI系统留出的API直接画图。根据这些依赖关系,对系统进行分层时,可以将他们划分到不同的层中。
在这里插入图片描述
如果更加细节,还可以继续分层划分不同的模块。

模块的目录结构

对于一个大型的项目,需要合理的目录结构来管理和组织文件。

一个好的目录结构,首先需要结构清晰,能够体现出不同模块之间的关系。比较常见的三种目录结构:

  • flat:所有的源文件都放在一个目录之下
  • shallow:各个模块放在各自的模块之下,主程序文件放在项目的顶层目录之下
  • deep:主程序文件和各个模块分别放在各自的模块之下

(个人常用示例, 属于flat类型):

- build // 项目构建文件夹
- lib // 库文件夹
- inc // include 头文件夹
- src // 各种源文件夹,也包含main.c

模块的封装

c语言中,一个模块一般对应一个C文件和一个头文件。模块的实现在C源文件中,头文件主要用来存放函数声明,留出模块的函数API,供其他模块调用。在别的模块中,使用预处理指令#include包含对应的头文件,就可以在当前模块中使用头文件中留出来的API。


总结

这是书中,C语言模块化编程思想的个人总结。书中拥有详细的内容,本人只是根据自己的需要进行的总结。如果您有好奇的地方可以阅读<嵌入式C语言自我修养>这本书第九章。

  • 13
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值