一、全局變量單獨(dú)編寫(很值得借鑒)。
一般習(xí)慣將不同功能模塊放到一個(gè)頭文件和一個(gè)C文件中。 例如是寫一些數(shù)學(xué)計(jì)算函數(shù):
//.h
#
#
int ; //聲明必要的全局變量
......
void fun(); //聲明必要的外部函數(shù)
.....
#endif
//.c
# ".h "
#
…
int ; //定義必要的全局變量和函數(shù)
void fun();
…
int a,b,c; //定義一些內(nèi)部使用的全局變量
void ();
//函數(shù)實(shí)現(xiàn)體
void fun()
{
…
}
void ()
{
…
}哪個(gè)C文件需要使用只需包含頭文件.h就可以了。
但是我認(rèn)為上面的方法雖然好,但是上面定義全局變量的方式在比較大的工程中引起不便,一個(gè)
模塊與其他模塊的數(shù)據(jù)傳遞最好通過專有的函數(shù)進(jìn)行,而不要直接通過數(shù)據(jù)單元直接傳遞(這是VC++的思想),因此不建議在模塊的頭文件中聲明全局變量;
全局變量最好統(tǒng)一定義在一個(gè)固定的文件中,所以可以采用下面的方法:
定義一個(gè).C文件來放全局變量,然后在與之相對(duì)應(yīng)的.H文件中來聲明全局變量
例如:
——————————————————————————————————
//.c
/*******定義本工程中所用到的全局變量*******/
int speed;
int ;
…
…
…——————————————————————————————————
//.H
/*******聲明本工程中所用到的全局變量*******/
int speed;
int ;
…
…——————————————————————————————————
這樣哪個(gè)文件用到這兩個(gè)變量就可以在該文件的開頭處寫上文件包含命令;例如aa.C文件要用到speed,toque兩個(gè)變量,可以在aa.H文件中包含.H文件。
——————————————————————————————————
//aa.H文件
# “.H”
…
void fun(); //聲明必要的接口函數(shù)
…
//aa.c文件
# “aa.H”//每個(gè)程序文件中包含自己的同名頭件
int a,b,c; //定義一些本文件內(nèi)部使用的局部變量
void ();
//函數(shù)實(shí)現(xiàn)體
void fun()
{
int d,e,f; //定義一些本函數(shù)內(nèi)部使用的局部變量
…
}
void ()
{
…
}
…——————————————————————————————————
在bb.c文件中用到aa.c文件中的函數(shù)void fun()或變量的文件可以這樣寫
//bb.H文件
# “aa.H”
…
int fun_1(void);//聲明本文件的接口函數(shù)
…
//bb.c文件
# “bb.H”
…
int fun_1(void)
{
…
fun();//調(diào)用aa.C文件中的fun()函數(shù)
…
}——————————————————————————————————
在主函數(shù)中可以這樣寫:
主文件main沒有自己的頭文件
//main.c文件
#
# “.H”
# “aa.H”
# “bb.H”
…
char fun_2();//聲明主文件所定義的函數(shù)
int i,j; //定義一些本模塊內(nèi)部使用的局部變量
char k;
…
void main()
{
…
fun();
…
i = fun_1();
…
k = fun_2();
…
}
char fun_2()
{
…
}——————————————————————————————————
這樣即不會(huì)報(bào)錯(cuò)又可以輕松使用全局變量。
二、如果在全局變量前加入或者const(隱式為類型的變量) 如下
// xxxx.h
...
const PI = 3.;
void* NULL = 0;
...
//這個(gè)頭文件是可以包含在多個(gè)編譯單元的。
三、頭文件編寫參考以下基本的規(guī)則
理想的情況下,一個(gè)可執(zhí)行的模塊提供一個(gè)公開的接口,即使用一個(gè)*.h文件暴露接口,但是,有時(shí)候,一個(gè)模塊需要提供不止一個(gè)接口,這時(shí),就要為每個(gè)定義的接口提供一個(gè)公開的接口。在C語言的里,每個(gè)C文件是一個(gè)模塊,頭文件為使用這個(gè)模塊的用戶提供接口,用戶只要包含相應(yīng)的頭文件就可以使用在這個(gè)頭文件中暴露的接口。所有的頭文件都建議參考以下的規(guī)則:
1. 頭文件中不能有可執(zhí)行代碼,也不能有數(shù)據(jù)的定義,只能有宏、類型(,,union,menu),數(shù)據(jù)和函數(shù)的聲明。
例如以下的代碼可以包含在頭文件里:
# “name”
long word;
menu{ flag1,flag2};
{
int x;
int y;
}Piont;
Fun(void);
int a;全局變量和函數(shù)的定義不能出現(xiàn)在*.h文件里。例如下面的代碼不能包含在頭文件:
int a;
void Fun1(void)
{
a++;
}
2. 頭文件中不能包本地?cái)?shù)據(jù)(模塊自己使用的數(shù)據(jù)或函數(shù),不被其他模塊使用)。
這一點(diǎn)相當(dāng)于面向?qū)ο蟪绦蛟O(shè)計(jì)里的私有成員,即只有模塊自己使用的函數(shù),數(shù)據(jù),不要用在頭文件里聲明c語言頭文件下載,只有模塊自己使用的宏,常量,類型也不要在頭文件里聲明,應(yīng)該在自己的*.c文件里聲明。
3. 含一些需要使用的聲明。在頭文件里聲明外部需要使用的數(shù)據(jù),函數(shù),宏,類型。
4. 防止被重復(fù)包含。使用下面的宏防止一個(gè)頭文件被重復(fù)包含。
#
#
#endif
四、頭文件編寫參考更多的規(guī)則(暫時(shí)只能理解1、2、3、4)
有一些頭文件是為用戶提供調(diào)用接口,這種頭文件中聲明了模塊中需要給其他模塊使用的函數(shù)和數(shù)據(jù),鑒于軟件質(zhì)量上的考慮,處理參考以上的規(guī)則,用來暴露接口的頭文件還需要參考更多的規(guī)則:
1. 一個(gè)模塊一個(gè)接口,不能幾個(gè)模塊用一個(gè)接口。
2. 文件名為和實(shí)現(xiàn)模塊的c文件相同。abc.c--abc.h
3. 盡量不要使用來聲明一些共享的數(shù)據(jù)。因?yàn)檫@種做法是不安全的,外部其他模塊的用戶可能不能完全理解這些變量的含義,最好提供函數(shù)訪問這些變量。
4. 盡量避免包含其他的頭文件,除非這些頭文件是獨(dú)立存在的。這一點(diǎn)的意思是c語言頭文件下載,在作為接口的頭文件中,盡量不要包含其他模塊的那些暴露*.C文件中內(nèi)容的頭文件,但是可以包含一些不是用來暴露接口的頭文件。
5. 不要包含那些只有在可執(zhí)行文件中才使用的頭文件,這些頭文件應(yīng)該在*.c文件中包含。這一點(diǎn)如同上一點(diǎn),為了提高接口的獨(dú)立性和透明度
6. 接口文件要有面向用戶的充足的注釋。從應(yīng)用角度描述個(gè)暴露的內(nèi)容。
7. 接口文件在發(fā)布后盡量避免修改,即使修改也要保證不影響用戶程序。
五、多個(gè)代碼文件使用一個(gè)接口文件(暫時(shí)不能完全理解)
這種頭文件用于那些認(rèn)為一個(gè)模塊使用一個(gè)文件太大的情況。對(duì)于這種情況對(duì)于這種情況在參考上述建議后,也要參考以下建議。
1. 多個(gè)代碼文件組成的一個(gè)模塊只有一個(gè)接口文件。因?yàn)檫@些文件完成的是一個(gè)模塊。
2. 使用模塊下文件命名
3. 不要濫用這種文件。
4. 有時(shí)候也會(huì)出現(xiàn)幾個(gè)*.c文件用于共享數(shù)據(jù)的*.h文件,這種文件的特點(diǎn)是在一個(gè)*.c文件里定義全局變量,而在其他*.c文件里使用,要將這種文件和用于暴露模塊接口的文件區(qū)別。
5. 一個(gè)模塊如果有幾個(gè)子模塊,可以用一個(gè)*.h文件暴露接口,在這個(gè)文件里用#包含每個(gè)子模塊的接口文件。
還有一種頭文件,說明性頭文件,這種頭文件不需要有一個(gè)對(duì)應(yīng)的代碼文件,在這種文件里大多包含了大量的宏定義,沒有暴露的數(shù)據(jù)變量和函數(shù)。這些文件給出以下建議:
1. 包含一些需要的概念性的東西.
2. 命名方式,定義的功能.h
3. 不包含任何其他的頭文件.
4. 不定義任何類型.