智能车制作

标题: .C .H文件组织如何组织 [打印本页]

作者: whut_wj    时间: 2009-5-9 08:45
标题: .C .H文件组织如何组织
理想的情况下,一个可执行的模块提供一个公开的接口,即使用一个*.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文件包含使用。
作者: chenrunshe_007    时间: 2009-5-9 09:52
我顶,不过WJ,我想问一句,我把全部PWM的代码都写在PWM.h中,也就是没有把.c源文件和.h头文件分开写。只要在工程的sources里添加PWM.h就照样可以使用,这样做很简便,行么?还是像你说的那样,把代码写在.c中,在.h中写函数接口的代码。
作者: whut_wj    时间: 2009-5-9 09:58
当然,你也可以只用一个头文件.
但是一个头文件,很多个C文件,
就如一只头,很多个身子一样.
不好组织,可读性也不强.
作者: leaf19881122    时间: 2009-8-4 20:39
我也遇到这样的问题,在PWM.h文件中定义了一个数组,在main.c和.PWM.c文件中都使用了PWM.h,最后出错了,但是如果两个c文件中都不包含也会出错,如果只是在main.c文件中定义数组,在PWM.c中好像不能用,
最后还是把PWM.c和PWM.h合二为一了。
作者: peilet    时间: 2009-8-9 11:05
我顶,不过WJ,我想问一句,我把全部PWM的代码都写在PWM.h中,也就是没有把.c源文件和.h头文件分开写。只要在工程的sources里添加PWM.h就照样可以使用,这样做很简便,行么?还是像你说的那样,把代码写在.c中,在.h ...
chenrunshe_007 发表于 2009-5-9 09:52


.c和.h其实在compiler看起来是一样的,只所以分开完全是为了程序可读性和管理性
作者: October    时间: 2009-9-15 15:28
赞!
作者: lfllcy    时间: 2010-3-18 10:45
了解!




欢迎光临 智能车制作 (http://dns.znczz.com/) Powered by Discuz! X3.2