本文介紹關於標頭檔案
#include
放在#include
之前報錯的問題。
原始檔1中:
#include
#include
//...
//...
原始檔2中:
#include
#include
//...
//...
編譯這兩個原始檔時,編譯出錯的內容如下:
definition of 'fd_set'
...\winsock2.h(143) : error c2011: 'timeval' : 'struct' type redefinition
...\include\winsock2.h(199) : error c2011: 'hostent' : 'struct' type redefinition
...\winsock2.h(212) : error c2011: 'netent' : 'struct' type redefinition
........
報錯的意思是所有與這兩個標頭檔案包含和
socket
介面有關的函式以及結構體等都提示這樣的錯誤:
redefinition
(函式以及結構體等型別重複定義)。
在原始檔1報錯的原因
windows.h
包含了winsock.h
和winsock2.h
(在老版本
windows
系統編譯下只包含
winsock.h
標頭檔案)。由於
winsock.h
和winsock2.h
這兩個標頭檔案是不能共存的,因為這兩個標頭檔案都存在一些相同的某變數或者函式定義名稱,在執行**中建立了物件(該物件都屬於
winsock.h
和winsock2.h
的),利用該物件進行訪問這兩個標頭檔案裡面的資訊,一旦出現一些變數的名稱都相同,進而導致這些變數重複定義的錯誤。
在原始檔2報錯的原因
像原始檔
1報錯的原因一樣,由於
winsock.h
和winsock2.h
是不能共存的,所以導致了重複定義的錯誤。
那麼問題來了,為什麼如下**,卻不會報錯呢。
在原始檔
1中修改**為:
#include
#include
//......
在原始檔
2中修改**為:
#include
#include
//....
為什麼把
winsock2.h
放在winsock.h
或者包含
winsock
的windows.h
的前面,再編譯這兩個檔案就不會出錯呢?
先放著這個問題在一邊暫時不思考,然後講一下
winsock.h
和winsock2.h
的主要區別。
winsock.h和winsock2.h相同點
1. winsock.h
和winsock2.h
都包含在同乙個目錄(如果在
vc6.0
環境下,包括
windows.h,
它們都在「
...\microsoft visual studio\vc98\include
」的資料夾裡面)。
winsock.h和winsock2.h區別
1. 版本區別,
winsock.h
版本為1.1
,而winsock2.h
版本為2.0.
2. winsock2
是winsock
的公升級版,
winsock2
對於對於
winsock
來說是向下相容的,由於因為相容,
winsock
有的東西,
winsock2
都有。
3. winsock
支援的協議比
winsock
要多。
4. winsock2
引用了新的
spi介面。主要意義是為了打破提供者的透明,開發者可以自己編寫
spi介面。
5. winsock2
擴充套件了更多與
winsock
所沒有的功能,比如說,擴充套件
tcp/ip
協議棧,
url以及網路安全控制等。
好了,理解了它們之間的關係,返回來看看那個不會報錯的問題。
winsock2.**件的部分內容
#ifndef _winsock2api_
#define _winsock2api_
#define _winsockapi_ /* prevent inclusion of winsock.h in windows.h */
//...
//...
#endif
說明:在
winsock.h
標頭檔案提前定義
winscok.h
的目的是阻止
windows.h
檔案裡面
#include
的定義以及在
winsock.h
檔案的定義
winsock.**件的部分內容
說明:進行巨集定義
winsockapi_
,也就是引用
winsock1.1版本
#ifndef _winsockapi_
#define _winsockapi_
windows.h
檔案部分內容
#if(_win32_winnt >= 0x0400)/
#include
#include
#else
#include
#endif /* _win32_winnt >= 0x0400 */
說明:由於在
vc6.0
環境下,該條件不滿足,所以只引用了
winsock.h
。然而在
vs環境下檢視不到有這部分內容,不過編譯時預設引用了
winsock.h
,也許visual studio
開發團隊對其進行優化了吧。至於
_win32_winnt
是什麼,我不再深究講述下去,在這裡討論沒意義,有興趣者自行研究。
沒有報錯的主要原因: 由於
windows.h
裡面包含了
winsock1.1
和winsock2.0
這兩個版本,但是
windows
編譯的通常情況下是選擇了
winsock.h
。首先引用了
#include
,由於winsock2.h
標頭檔案裡「
#define _winsockapi_
」預定義了巨集,如果系統再指向下一步
#include
(或者#include
),由於
#ifdef
語句判斷了
winsock
在winsock2.h
檔案早就定義過,所以就不會重複再定義這個了。
如果說,引用
winsock.h
再在引用
winsock2.h
的話,winsock
在其檔案早就定義了,在
winsock2.h
當中,#ifdef
判斷的是
winsock2.0
有沒有定義,顯然是滿足條件的,所以在定義
winscok2.0
巨集的同時就會重複定義
wiinsock1.1
。所以,如果
winsock2.h
預先被引用的話,下乙個
winsock.h
就不會被用到,這就是所謂的兩者不能共存。
關於標頭檔案
自定義標頭檔案通常放在使用該標頭檔案的原始檔所在的目錄中,並使用 include myhead.h 來包含。標頭檔案是不編譯的,因為c語言編譯過程之前有個預編譯過程。在這個過程中用標頭檔案中的內容替換原始檔中 include 命令,所以在編譯器看來,沒有標頭檔案,只有原始檔。預編譯過程還包括條件編譯...
python程式設計標頭檔案 python標頭檔案怎麼寫
本文主要以python2為例。首先介紹一下python標頭檔案的程式設計風格,然後再給大家詳細介紹import部分的基本用法。這兩個部分就是python中標頭檔案的組成模組。程式設計風格 usr bin env python 在檔案頭部 第一行 加上 設定 python 直譯器 coding utf...
關於time h標頭檔案
編輯 1 2 3 4 5 6 7 8 include include intmain 編輯 time t time time t timer 得到從標準計時點 一般是1970年1月1日午夜 到當前時間的秒數。clock t clock void 得到從程式啟動到此次 函式呼叫時累計的毫秒數。編輯 函...