C 標頭檔案 作用
一般習慣將不同功能模組放到一個標頭檔案和一個C檔案中。
例如是寫一些數學計算函式:
//mymath.h
#ifndef _mymath_H
#define _mymath_H
extern int Global_A; //宣告必要的全域性變數
......
extern void fun(); //宣告必要的外部函式
.....
#endif
//mymath.c
#include "mymath.h "
#include
…
int Global_A; //定義必要的全域性變數和函式
void fun();
…
int a,b,c; //定義一些內部使用的全域性變數
void somefun();
//函式實現體
void fun()
{
…
}
void somefun()
{
…
}
哪個C檔案需要使用只需包含標頭檔案mymath.h就可以了。
但是我認為上面的方法雖然好,但是上面定義全域性變數的方式在比較大的工程中引起不便,一個模組與其他模組的資料傳遞最好通過專有的函式進行,而不要直接通過資料單元直接傳遞(這是VC++的思想),因此不建議在模組的標頭檔案中宣告全域性變數;全域性變數最好統一定義在一個固定的檔案中,所以可以採用下面的方法:
定義一個Globel_Var.C檔案來放全域性變數,然後在與之相對應的Globel_Var.H檔案中來宣告全域性變數
例如
——————————————————————————————————
//Globel_Var.C
/*******定義本工程中所用到的全域性變數*******/
int speed;
int torque;
…
…
…
——————————————————————————————————
//Globel_Var.H
/*******宣告本工程中所用到的全域性變數*******/
extern int speed;
extern int torque;
…
…
——————————————————————————————————
這樣哪個檔案用到這兩個變數就可以在該檔案的開頭處寫上檔案包含命令;例如aa.C檔案要用到speed,toque兩個變數,可以在aa.H檔案中包含Globel_Var.H檔案。
——————————————————————————————————
//aa.H檔案
#include “Globel_Var.H”
…
extern void fun(); //宣告必要的介面函式
…
//aa.C檔案
#include “aa.H”//每個程式檔案中包含自己的同名頭件
int a,b,c; //定義一些本檔案內部使用的區域性變數
…
//函式實現體
void fun()
{
int d,e,f; //定義一些本函式內部使用的區域性變數
…
}
void somefun()
{
…
}
…
——————————————————————————————————
在bb.C檔案中用到aa.C檔案中的函式void fun()或變數的檔案可以這樣寫
//bb.H檔案
#include “aa.H”
…
extern int fun_1(void);//宣告本檔案的介面函式
…
//bb.C檔案
#include “bb.H”
…
int fun_1(void)
{
…
fun();//呼叫aa.C檔案中的fun()函式
…
}
——————————————————————————————————
在主函式中可以這樣寫:主檔案main沒有自己的標頭檔案
//main.C檔案
#include
#include “Glable_Var.H”
#include “aa.H”
#include “bb.H”
…
char fun_2(int x,char y);//宣告主檔案所定義的函式
int i,j; //定義一些本模組內部使用的區域性變數
char k;
…
void main()
{
…
fun();
…
i = Fun_1();
…
k = fun_2();
…
}
char fun_2()
{
…
}
——————————————————————————————————
這樣即不會報錯又可以輕鬆使用全域性變數。
二、如果在全域性變數前加入static或者const(隱式static)
如下
// xxxx.h
...
const double PI = 3.1415926;
static void* NULL = 0;
...
//
這個標頭檔案是可以包含在多個編譯單元的。
三、理想的情況下,一個可執行的模組提供一個公開的介面,即使用一個*.h檔案暴露介面,但是,有時候,一個模組需要提供不止一個介面,這時,就要為每個定義的介面提供一個公開的介面。在C語言的裡,每個C檔案是一個模組,標頭檔案為使用這個模組的使用者提供介面,使用者只要包含相應的標頭檔案就可以使用在這個標頭檔案中暴露的介面。所有的標頭檔案都建議參考以下的規則:
1,標頭檔案中不能有可執行程式碼,也不能有資料的定義,只能有巨集、型別(typedef,struct,union,menu),資料和函式的宣告。例如以下的程式碼可以包含在標頭檔案裡:
#define NAMESTRING “name”
typedef unsigned 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,標頭檔案中不能包本地資料(模組自己使用的資料或函式,不被其他模組使用)。這一點相當於物件導向程式設計裡的私有成員,即只有模組自己使用的函式,資料,不要用extern在標頭檔案裡宣告,只有模組自己使用的巨集,常量,型別也不要在標頭檔案裡宣告,應該在自己的*.c檔案裡宣告。
3,含一些需要使用的宣告。在標頭檔案裡宣告外部需要使用的資料,函式,巨集,型別。
4,防止被重複包含。使用下面的巨集防止一個標頭檔案被重複包含。
#ifndef MY_INCLUDE_H
#define MY_INCLUDE_H
#endif
四、有一些標頭檔案是為使用者提供呼叫介面,這種標頭檔案中宣告瞭模組中需要給其他模組使用的函式和資料,鑑於軟體質量上的考慮,處理參考以上的規則,用來暴露介面的標頭檔案還需要參考更多的規則:
一個模組一個介面,不能幾個模組用一個介面。
檔名為和實現模組的c檔案相同。abc.c--abc.h
儘量不要使用extern來宣告一些共享的資料。因為這種做法是不安全的,外部其他模組的使用者可能不能完全理解這些變數的含義,最好提供函式訪問這些變數。
儘量避免包含其他的標頭檔案,除非這些標頭檔案是獨立存在的。這一點的意思是,在作為介面的標頭檔案中,儘量不要包含其他模組的那些暴露*.C檔案中內容的標頭檔案,但是可以包含一些不是用來暴露介面的標頭檔案。
不要包含那些只有在可執行檔案中才使用的標頭檔案,這些標頭檔案應該在*.c檔案中包含。這一點如同上一點,為了提高介面的獨立性和透明度
介面檔案要有面向使用者的充足的註釋。從應用角度描述個暴露的內容。
介面檔案在釋出後儘量避免修改,即使修改也要保證不影響使用者程式。
五、多個程式碼檔案使用一個介面檔案:這種標頭檔案用於那些認為一個模組使用一個檔案太大的情況。對於這種情況對於這種情況在參考上述建議後,也要參考以下建議。
多個程式碼檔案組成的一個模組只有一個介面檔案。因為這些檔案完成的是一個模組。
使用模組下檔案命名
不要濫用這種檔案。
有時候也會出現幾個*.c檔案用於共享資料的*.h檔案,這種檔案的特點是在一個*.c檔案裡定義全域性變數,而在其他*.c檔案裡使用,要將這種檔案和用於暴露模組介面的檔案區別。
一個模組如果有幾個子模組,可以用一個*.h檔案暴露介面,在這個檔案裡用#include包含每個子模組的介面檔案。
還有一種標頭檔案,說明性標頭檔案,這種標頭檔案不需要有一個對應的程式碼檔案,在這種檔案裡大多包含了大量的巨集定義,沒有暴露的資料變數和函式。這些檔案給出以下建議:
1,包含一些需要的概念性的東西.
2,命名方式,定義的功能.h
3,不包含任何其他的標頭檔案.
4,不定義任何型別.
5,不包含任何資料和函式宣告.
上面介紹了C標頭檔案的一些建議,下面介紹C程式碼檔案*.c檔案的一些建議,*.c檔案是C語言中生成彙編程式碼和機器碼的內容,要注意以下建議:
1.命名方式 模組名.c
2,用static修飾本地的資料和函式。
3,不要使用externa。這是在*.h中使用的,可以被包含進來。
4,無論什麼時候定義內部的物件,確保獨立與其他執行檔案。
5,這個檔案裡必須包含相應功能函式。
結束語:上面介紹了一些C檔案組織的建議,用於提高C語言專案的質量,在以後的C專案組織中,學習物件導向和COM的思想,將這些思想加入到C程式中,能夠寫出更高質量的程式碼。上面的建議在具體的專案裡應該靈活運用。另外,C工程中經常有一些彙編程式碼檔案,這些檔案也要使有*.h標頭檔案暴露其中的資料和函式,以便其他*.c檔案包含使用。
例如是寫一些數學計算函式:
//mymath.h
#ifndef _mymath_H
#define _mymath_H
extern int Global_A; //宣告必要的全域性變數
......
extern void fun(); //宣告必要的外部函式
.....
#endif
//mymath.c
#include "mymath.h "
#include
…
int Global_A; //定義必要的全域性變數和函式
void fun();
…
int a,b,c; //定義一些內部使用的全域性變數
void somefun();
//函式實現體
void fun()
{
…
}
void somefun()
{
…
}
哪個C檔案需要使用只需包含標頭檔案mymath.h就可以了。
但是我認為上面的方法雖然好,但是上面定義全域性變數的方式在比較大的工程中引起不便,一個模組與其他模組的資料傳遞最好通過專有的函式進行,而不要直接通過資料單元直接傳遞(這是VC++的思想),因此不建議在模組的標頭檔案中宣告全域性變數;全域性變數最好統一定義在一個固定的檔案中,所以可以採用下面的方法:
定義一個Globel_Var.C檔案來放全域性變數,然後在與之相對應的Globel_Var.H檔案中來宣告全域性變數
例如
——————————————————————————————————
//Globel_Var.C
/*******定義本工程中所用到的全域性變數*******/
int speed;
int torque;
…
…
…
——————————————————————————————————
//Globel_Var.H
/*******宣告本工程中所用到的全域性變數*******/
extern int speed;
extern int torque;
…
…
——————————————————————————————————
這樣哪個檔案用到這兩個變數就可以在該檔案的開頭處寫上檔案包含命令;例如aa.C檔案要用到speed,toque兩個變數,可以在aa.H檔案中包含Globel_Var.H檔案。
——————————————————————————————————
//aa.H檔案
#include “Globel_Var.H”
…
extern void fun(); //宣告必要的介面函式
…
//aa.C檔案
#include “aa.H”//每個程式檔案中包含自己的同名頭件
int a,b,c; //定義一些本檔案內部使用的區域性變數
…
//函式實現體
void fun()
{
int d,e,f; //定義一些本函式內部使用的區域性變數
…
}
void somefun()
{
…
}
…
——————————————————————————————————
在bb.C檔案中用到aa.C檔案中的函式void fun()或變數的檔案可以這樣寫
//bb.H檔案
#include “aa.H”
…
extern int fun_1(void);//宣告本檔案的介面函式
…
//bb.C檔案
#include “bb.H”
…
int fun_1(void)
{
…
fun();//呼叫aa.C檔案中的fun()函式
…
}
——————————————————————————————————
在主函式中可以這樣寫:主檔案main沒有自己的標頭檔案
//main.C檔案
#include
#include “Glable_Var.H”
#include “aa.H”
#include “bb.H”
…
char fun_2(int x,char y);//宣告主檔案所定義的函式
int i,j; //定義一些本模組內部使用的區域性變數
char k;
…
void main()
{
…
fun();
…
i = Fun_1();
…
k = fun_2();
…
}
char fun_2()
{
…
}
——————————————————————————————————
這樣即不會報錯又可以輕鬆使用全域性變數。
二、如果在全域性變數前加入static或者const(隱式static)
如下
// xxxx.h
...
const double PI = 3.1415926;
static void* NULL = 0;
...
//
這個標頭檔案是可以包含在多個編譯單元的。
三、理想的情況下,一個可執行的模組提供一個公開的介面,即使用一個*.h檔案暴露介面,但是,有時候,一個模組需要提供不止一個介面,這時,就要為每個定義的介面提供一個公開的介面。在C語言的裡,每個C檔案是一個模組,標頭檔案為使用這個模組的使用者提供介面,使用者只要包含相應的標頭檔案就可以使用在這個標頭檔案中暴露的介面。所有的標頭檔案都建議參考以下的規則:
1,標頭檔案中不能有可執行程式碼,也不能有資料的定義,只能有巨集、型別(typedef,struct,union,menu),資料和函式的宣告。例如以下的程式碼可以包含在標頭檔案裡:
#define NAMESTRING “name”
typedef unsigned 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,標頭檔案中不能包本地資料(模組自己使用的資料或函式,不被其他模組使用)。這一點相當於物件導向程式設計裡的私有成員,即只有模組自己使用的函式,資料,不要用extern在標頭檔案裡宣告,只有模組自己使用的巨集,常量,型別也不要在標頭檔案裡宣告,應該在自己的*.c檔案裡宣告。
3,含一些需要使用的宣告。在標頭檔案裡宣告外部需要使用的資料,函式,巨集,型別。
4,防止被重複包含。使用下面的巨集防止一個標頭檔案被重複包含。
#ifndef MY_INCLUDE_H
#define MY_INCLUDE_H
#endif
四、有一些標頭檔案是為使用者提供呼叫介面,這種標頭檔案中宣告瞭模組中需要給其他模組使用的函式和資料,鑑於軟體質量上的考慮,處理參考以上的規則,用來暴露介面的標頭檔案還需要參考更多的規則:
一個模組一個介面,不能幾個模組用一個介面。
檔名為和實現模組的c檔案相同。abc.c--abc.h
儘量不要使用extern來宣告一些共享的資料。因為這種做法是不安全的,外部其他模組的使用者可能不能完全理解這些變數的含義,最好提供函式訪問這些變數。
儘量避免包含其他的標頭檔案,除非這些標頭檔案是獨立存在的。這一點的意思是,在作為介面的標頭檔案中,儘量不要包含其他模組的那些暴露*.C檔案中內容的標頭檔案,但是可以包含一些不是用來暴露介面的標頭檔案。
不要包含那些只有在可執行檔案中才使用的標頭檔案,這些標頭檔案應該在*.c檔案中包含。這一點如同上一點,為了提高介面的獨立性和透明度
介面檔案要有面向使用者的充足的註釋。從應用角度描述個暴露的內容。
介面檔案在釋出後儘量避免修改,即使修改也要保證不影響使用者程式。
五、多個程式碼檔案使用一個介面檔案:這種標頭檔案用於那些認為一個模組使用一個檔案太大的情況。對於這種情況對於這種情況在參考上述建議後,也要參考以下建議。
多個程式碼檔案組成的一個模組只有一個介面檔案。因為這些檔案完成的是一個模組。
使用模組下檔案命名
不要濫用這種檔案。
有時候也會出現幾個*.c檔案用於共享資料的*.h檔案,這種檔案的特點是在一個*.c檔案裡定義全域性變數,而在其他*.c檔案裡使用,要將這種檔案和用於暴露模組介面的檔案區別。
一個模組如果有幾個子模組,可以用一個*.h檔案暴露介面,在這個檔案裡用#include包含每個子模組的介面檔案。
還有一種標頭檔案,說明性標頭檔案,這種標頭檔案不需要有一個對應的程式碼檔案,在這種檔案裡大多包含了大量的巨集定義,沒有暴露的資料變數和函式。這些檔案給出以下建議:
1,包含一些需要的概念性的東西.
2,命名方式,定義的功能.h
3,不包含任何其他的標頭檔案.
4,不定義任何型別.
5,不包含任何資料和函式宣告.
上面介紹了C標頭檔案的一些建議,下面介紹C程式碼檔案*.c檔案的一些建議,*.c檔案是C語言中生成彙編程式碼和機器碼的內容,要注意以下建議:
1.命名方式 模組名.c
2,用static修飾本地的資料和函式。
3,不要使用externa。這是在*.h中使用的,可以被包含進來。
4,無論什麼時候定義內部的物件,確保獨立與其他執行檔案。
5,這個檔案裡必須包含相應功能函式。
結束語:上面介紹了一些C檔案組織的建議,用於提高C語言專案的質量,在以後的C專案組織中,學習物件導向和COM的思想,將這些思想加入到C程式中,能夠寫出更高質量的程式碼。上面的建議在具體的專案裡應該靈活運用。另外,C工程中經常有一些彙編程式碼檔案,這些檔案也要使有*.h標頭檔案暴露其中的資料和函式,以便其他*.c檔案包含使用。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/25897606/viewspace-747080/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- C語言標頭檔案#include的作用C語言
- 標頭檔案的作用分析
- linux 標頭檔案 作用Linux
- C 語言標頭檔案作用的簡單理解
- C 標頭檔案
- C 語言的變數作用域及標頭檔案變數
- C語言標頭檔案#include的作用是什麼?C語言
- C++理論梳理3——深刻理解標頭檔案的作用C++
- C/C++標頭檔案一覽C++
- C/C++標頭檔案說明C++
- C/C++標頭檔案太難記?一個萬能標頭檔案全搞定!C++
- c++筆記_標頭檔案C++筆記
- C語言 - 標頭檔案包含C語言
- C/C++標頭檔案一覽(轉)C++
- POSIX.1 and ISO C標準標頭檔案
- C++標準庫標頭檔案介紹C++
- 關於C++的標頭檔案C++
- C++ 預編譯標頭檔案C++編譯
- 8.13 標頭檔案剖析:標頭檔案路徑(下)
- C++標準庫名字和標頭檔案--表C++
- C++ include標頭檔案引入規則C++
- macos新增c++萬能標頭檔案MacC++
- 附錄: 標準C++常用標頭檔案及描述C++
- C++ 標頭檔案的包含順序研究C++
- C語言標頭檔案的使用(轉載)C語言
- C語言關於標頭檔案的使用C語言
- #include sys/xxx.h標頭檔案 UNIX標頭檔案
- locate標頭檔案和庫檔案
- 祖傳標頭檔案
- 標頭檔案講解
- C語言標頭檔案到底是什麼?C語言
- VS Code 配置或新增 C 標頭檔案路徑
- C++ 字元處理函式(cctype標頭檔案)C++字元函式
- C++ 字串 cctype 標頭檔案標準庫處理函式C++字串函式
- C語言rewind()函式:將檔案指標重新指向檔案開頭C語言函式指標
- C++自學34:原始檔與標頭檔案(pragma/ifndef/endif/ifdef)C++
- fcntl.h標頭檔案
- 什麼是 標頭檔案