c语言模块化程序设计,C语言程序模块化
大型软件项目通常包含许多复杂的功能。要实现这个项目,一个程序员是无法单独完成的,往往需要团队的有效分工与合作。此外,在一个基于C代码的完整项目中,往往需要添加一些其他语言的代码,例如,C代码和汇编代码的混合使用,以及C文件和C的同时使用,这些都增加了一个软件项目的复杂性。为了提高软件质量,合理地组织各种代码和文件是非常重要的。组织代码和文档的目的是使团队协作更加有效,使软件项目具有良好的可扩展性、可维护性、可移植性、可裁剪性和可测试性,防止错误,提高软件稳定性。
软件项目通常采用分层结构开发和模块化开发。例如,嵌入式软件项目可以具有驱动程序层、操作系统层、功能层和应用层。每一层都使用其下层提供的接口,并为其上层提供调用接口。模块是在每一层中完成一个功能的单元。比如驱动层每个设备的驱动都是一个模块,应用层每个应用都是一个模块。该模块利用下层和同层其他模块提供的接口完成特定功能,并为上层和同层其他模块提供调用接口。
这里的接口指的是一个功能模块公开并向其他模块提供对特定功能的访问的方法。根据C语言的特点,使用*。c文件实现该模块的功能,并使用*。h文件来公开单元的接口。在*。h文件,声明其他外部模块可能使用的函数、数据类型、全局变量、类型定义、宏定义和常量定义。外部模块只能通过包含*来使用相应的功能。h文件。当然,模块可以细分为子模块。虽然这里说的接口不同于COM(通用组件模型)中定义的接口,但是根据COM中对接口的讨论,为了在修改软件时,使一个模块的修改不影响其他模块,一个模块的修改不会导致其他模块的修改,所以,在接口第一次发布后,修改*。h文件不能导致其他使用这个接口的模块需要重写。
本组织的基本建议
使用分层和模块化的软件开发模型。每个模块只能使用本层和下一层模块提供的接口。
每个模块的文件包存储在一个独立的文件夹中。通常,实现一个模块有多个文件,这些相关的文件应该存储在一个文件夹中。
硬件相关代码和操作系统相关代码与纯C代码独立保存,方便软件移植。
与声明分开,使用*。h文件来公开模块需要对外提供的函数、宏、类型、常量和全局变量。尽量让模块对外透明。用户在使用模块功能时不需要知道具体的实现。文件一旦发布,就必须仔细修改。
文件夹和文件的名字应该反映模块的功能,所以名字应该有意义。
正式版和测试版使用统一的文件,用宏控制是否生成测试输出。
必要的注释对于提高文档的可读性是必不可少的。
对于头文件,建议参考以下规则
头文件中不能有可执行代码或数据定义,只能有宏、类型(typedef、struct、union、menu)、数据和函数的声明。
例如,以下代码可以包含在头文件中:
#定义名称字符串“名称”
typedef取消长单词的签名;
菜单
{
flag1
flag2
};
typedefstruct
{
intx
inty
} Piont
extent fun(void);
extent int a;
全局变量和函数的定义不能出现在*。h文件。例如,下列代码不能包含在头文件中:
inta
voidFun1(无效)
{
a;
}
头文件不能包含本地数据(模块本身使用的数据或函数,但不被其他模块使用)。这相当于面向对象编程中的私有成员,即只有模块本身使用的函数和数据不应该在头文件中用extent声明,只有模块本身使用的宏、常量和类型不应该在头文件中声明,而应该在自己的*中声明。c文件。
包含一些需要用到的语句。在头文件中声明需要外部使用的数据、函数、宏和类型。
防止重复包含。使用下面的宏来防止头文件被重复包含。
#ifndef MY_INCLUDE_H
#定义我的包含
内容头文件
#endif
包含extern C ,以便程序可以在C编译器中编译。
#ifdef__cplusplus
外部 C{
#endif
函数声明
#ifdef__cplusplus
}
#enfif
externC 修改的变量和函数按照C语言编译连接;没有extern“C”声明的编译方法,作为面向对象的语言,C支持函数重载,而编程语言C不支持。C在符号库中编译的函数名称与C语言中的不同。例如,假设一个函数的原型是:
voidfoo(int x,inty);这个函数经过C编译器编译后在符号库中的名字是_foo,而C编译器会生成类似_foo_int_int这样的名字(不同的编译器可能会生成不同的名字,但都采用相同的机制,生成的新名字叫做“mangledname”)。name _foo_int_int包含函数名,函数参数的个数和类型信息,C依靠这个机制实现函数重载。比如在C中,函数void foo(intx,int y)和void foo(intx,floaty)编译生成的符号是不同的,后者是_foo_int_float。同样,C中的变量除了支持局部变量外,还支持类成员变量和全局变量。用户编写的程序的类成员变量可能与全局变量同名,用“.”来区分。本质上,编译时,编译器为类中的变量取一个唯一的名字,类似于函数的处理,不同于用户程序中同名的全局变量名。在externC 声明后添加编译和连接,根据C编译器生成的symbol _foo强制C连接器链接。
组合是:
#ifndef MY_INCLUDE_H
#定义我的包含
#ifdef __cplusplus
外部 C{
#endif
函数声明
#ifdef __cplusplus
#enfif
#endif
确保用户在使用该头文件时,不需要包含使用该头文件的其他先决头文件,即该头文件中已经包含了要使用的头文件。例如,area.h头文件包含与区域相关的操作。要使用这个头文件,不需要包含关于点操作的头文件point . h。用户在使用area.h时不需要手动包含point.h,因为我们已经在area.h中包含了这个带有# include“point . h”的头文件。
用于公开接口的头文件还需要引用更多的规则:
1.一个模块有一个接口,几个模块不能用一个接口。
2.文件名与实现模块的C文件相同。abc.c - abc.h
3.尽量不要用extern来声明一些共享数据。因为这种方法不安全,所以其他外部模块的用户可能不会完全理解这些变量的含义。最好提供GetPut函数来访问这些变量。
4.尽量避免包含其他头文件,除非这些头文件独立存在。这意味着用作接口的头文件应该尽量不包含那些公开*内容的其他模块的头文件。c文件,但是一些不用于公开接口的头文件可以包装。
5.不要包含只在可执行文件中使用的头文件。这些头文件应该包含在*。c文件。这个和上一点一样,为了提高界面的独立性和透明性。
6.界面文件应该为用户提供足够的注释。从应用的角度描述一个暴露的内容。
7.接口文件发布后尽量避免修改,即使修改也要保证不影响用户程序。
多个代码文件使用一个接口文件:这个头文件用于那些被认为对于一个模块来说太大而不能使用一个文件的情况。添加以下建议。
1.由多个代码文件组成的模块只有一个接口文件。因为这些文件完成了一个模块。
2.使用模块下的文件命名系统名称来命名模块名称
3.不要滥用这种文档。
4.有时候,几个*。c文件将用于*。h文件的同向数据。这个文件的特点是在一个*中定义全局变量。c文件并在其他*中使用它。c文件。这个文件应该与用于公开模块接口的文件区分开来。
5.如果一个模块有几个子模块,您可以使用*。h文件来公开接口。在这个文件中,使用#include包含每个子模块的接口文件。
还有一个头文件,描述性头文件,不需要对应的代码文件。这些文件大多包含大量的宏定义,没有暴露的数据变量和函数。这些文件给出了以下建议:
1,包含一些需要的概念性的东西。
2、命名方法,定义函数。h
3,不包含任何其他头文件。
4.没有定义类型。
5、不包含任何数据和函数声明。
上面介绍了C头文件的一些建议,C代码文件*的一些建议。下面介绍c文件。*.C文件是用C语言生成汇编代码和机器码的内容。请注意以下建议:
1.命名方法模块名称。c
2.用static修饰本地数据和函数。
3.不要使用外部。这在*中使用。h和可以包括在内。
4.无论何时定义内部对象,都要确保独立于其他可执行文件。
5.这个文件必须包含相应的函数。
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。