文件模块C语言模块化要点

文章结束给大家来个程序员笑话:[M]

       在C语言的应用范畴,如通讯范畴和嵌入式系统范畴,一个的软件项目平日包含很多庞杂的功能,实现这个项目不是一个程序员单枪匹马可以胜任的,往往需要一个团队的有效合作,另外,在一个以C代码为主的完整的项目中,经常也需要参加一些其他语言的代码,例如,C代码和汇编代码的混合应用,C文件和C++的同时应用。这些都增加了一个软件项目标庞杂水平,为了提高软件质量,公道组织的各种代码和文件是非常重要的。      
      
    组织代码和文件的目标是为了使团队合作更加有效,使软件项目有精良的可扩展性、可维护性、可移植性、可裁减、可测试性,防止错误产生,提高软件的稳定性。平日情况下,软件项目采取层次化结构和模块化开发的方法,例如,一个嵌入式软件项目可能有驱动层,操作系统层,功能层,应用程序层,每个层应用它的下层供给的接口,并为它的下层供给调用接口,模块则是每个层中完成一个功能的单元,例如驱动层的每个设备的驱动就是一个模块,应用层的每个应用程序就是一个模块,模块应用下层供给的接口和同层其他模块供给的接口,完成特定功能,为下层和同层的其他模块供给调用接口。       
       
    这里的接口是指一个功能模块暴露出来的,供给给其他模块的拜访详细功能的方法。根据C语言的特点,应用*.c文件实现模块的功能,应用*.h文件暴露单元的接口,在*.h文件里声明外部其他模块可能是用的函数,数据类型,全局变量,类型定义,宏定义和常量定义.外部模块只需包含*.h文件就能够应用相应的功能.当然,模块可以在细化为子模块.虽然我们这里说的接口和COM(通用组件模型)里定义的接口不同,但是,根据COM里对接口的讨论,为了使软件在修改时,一个模块的修改不会影响到其他模块的一个模块的修改不会导致其他模块也需要修改,所以,接口第一次宣布后,修改*.h文件不能导致应用这个接口的其他模块需要重新编写.      
       
    根据C语言的特点,并鉴戒一些成熟软件项目代码,总结C项目中代码文件组织的基本提议:      
    1,应用层次化和模块化的软件开发模型.每个模块只能应用地点层和下一层模块供给的接口.      
    2,每个模块的文件包存在独立的一个文件夹中.平日情况下,实现一个模块的文件不止一个,这些相干的文件应该保存在一个文件夹中.      
    3,用于模块裁减的条件编译宏保存在一个独立的文件里,便于软件裁减.      
    4,硬件相干代码和操作系统相干代码与纯C代码绝对独立保存,以便于软件移植.      
    5,声明和定义离开,应用*.h文件暴露模块需要供给给外部的函数,宏,类型,常量,全局变量,尽量做到模块对外部透明,用户在应用模块功能时不需要懂得详细的实现,文件一旦宣布,要修改一定要很慎重,      
    6,文件夹和文件定名要可以反映出模块的功能.      
    7,正式版本和测试版本应用同一文件,应用宏控制是否产生测试输出。      
    8,必要的注释弗成缺少。      
       
    理想的情况下,一个可执行的模块供给一个公开的接口,即应用一个*.h文件暴露接口,但是,有时候,一个模块需要供给不止一个接口,这时,就要为每个定义的接口供给一个公开的接口。在C语言的里,每个C文件是一个模块,头文件为应用这个模块的用户供给接口,用户只要包含相应的头文件就能够应用在这个头文件中暴露的接口。全部的头文件都提议参考以下的规矩:      
       
    1,   头文件中不能有可执行代码,也不能有数据的定义,只能有宏、类型(typedef,struct,union,menu),数据和函数的声明。例如以下的代码可以包含在头文件里:      
    #define       NAMESTRING       “name”      
    typedef       unsign       long       word;      
    menu{      
    flag1;      
    flag2;      
    };      
    typedef       struct{      
    int       x;      
    int       y;      
    }       Piont;      
    extent       Fun(void);      
    extent       int       a;      
    全局变量和函数的定义不能出现在*.h文件里。例如上面的代码不能包含在头文件:      
    int       a;      
    void       Fun1(void)      
    {      
                    a++;      
    }      
       
    2,头文件中不能包当地数据(模块自己应用的数据或函数,不被其他模块应用)。这一点相当于面向对象程序设计里的私有成员,即只有模块自己应用的函数,数据,不要用extent在头文件里声明,只有模块自己应用的宏,常量,类型也不要在头文件里声明,应该在自己的*.c文件里声明。      
    3,含一些需要应用的声明。在头文件里声明外部需要应用的数据,函数,宏,类型。      
    4,防止被重复包含。应用上面的宏防止一个头文件被重复包含。      
    #ifndef       MY_INCLUDE_H      
    #define       MY_INCLUDE_H      
    <头文件内容 >      
    #endif      
    5,包含extern       "C",使的程序可以在C++编译器被编译      
    #ifdef       __cplusplus      
   extern       "C"{      
    #endif      
    <函数声明 >      
    #ifdef       __cplusplus      
     }      
    #enfif      
     被extern       "C"修饰的变量和函数是按照C语言方式编译和连接的;未加extern       “C”声明时的编译方式,作为一种面向对象的语言,C++支撑函数重载,而过程式语言C则不支撑。函数被C++编译后在符号库中的名字与C语言的不同。例如,假设某个函数的原型为:         
    void foo( int x, int  y  );该函数被C编译器编译后在符号库中的名字为_foo,而C++编译器则会产生像_foo_int_int之类的名字(不同的编译器可能生成的名字不同,但是都采取了雷同的机制,生成的新名字称为“mangled      name”)。_foo_int_int这样的名字包含了函数名、函数参数数量及类型信息,C++就是靠这种机制来实现函数重载的。例如,在C++中,函数void   foo( int x, int y)与void foo( int x, float  y)编译生成的符号是不雷同的,后者为_foo_int_float。 同样地,C++中的变量除支撑局部变量外,还支撑类成员变量和全局变量。用户所编写程序的类成员变量可能与全局变量同名,我们以"."来区分。而本质上,编译器在进行编译时,与函数的处理相似,也为类中的变量取了一个独一无二的名字,这个名字与用户程序中同名的全局变量名字不同。加extern       "C"声明后的编译和连接,强制C++连接器按照C编译器产生的符号_foo链接。     

    每日一道理
我拽着春姑娘的衣裙,春姑娘把我带到了绿色的世界里。

    
    6,保证在应用这个头文件时,用户不必再包含应用此头文件的其他前提头文件,即要应用的头文件已经包含在此头文件里。例如:area.h头文件包含了面积相干的操作,要应用这个头文件不需同时包含了关于点操作的头文件piont.h。用户在应用area.h时不需要手动包含piont.h,因为我们已经在 area.h中用#include       “point.h”包含了这个头文件。      
       
    有一些头文件是为用户供给调用接口,这种头文件中声明白模块中需要给其他模块应用的函数和数据,鉴于软件质量上的斟酌,处理参考以上的规矩,用来暴露接口的头文件还需要参考更多的规矩:      
    1,一个模块一个接口,不能几个模块用一个接口。      
    2,文件名为和实现模块的c文件雷同。abc.c--abc.h      
    3,尽量不要应用extern来声明一些共享的数据。因为这种做法是不安全的,外部其他模块的用户可能不能完整理解这些变量的含义,最好供给函数拜访这些变量。      
    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,不要应用external。这是在*.h中应用的,可以被包含进来。      
    4,无论什么时候定义内部的对象,确保独立与其他执行文件。      
    5,这个文件里必须包含相应功能函数。      
       
    上面介绍了一些C文件组织的提议,用于提高C语言项目标质量,在当前的C项目组织中,学习面向对象和COM的思惟,将这些思惟参加到C程序中,可以写出更高质量的代码。上面的提议在详细的项目里应该灵活运用,附录里有*.h头文件和*.c代码文件的模版,在工程中可以作为参考。另外,C工程中经常有一些汇编代码文件,这些文件也要使有*.h头文件暴露其中的数据和函数,以便其他*.c文件包含应用。

文章结束给大家分享下程序员的一些笑话语录: PC软件体积大,是因为一个PC软件功能往往较多,能够满足你一个方面的需求,而一个iphone软件往往没几行代码,干一件很小的事情,自然需要的软件就多。就像吃西瓜和吃瓜子的来比数目,单位不同啊。

posted @ 2013-05-12 23:13  xinyuyuanm  阅读(510)  评论(0编辑  收藏  举报