問題:徹底無語了,不小心某個文件包含了windows.h頭文件,而windows.h文件里面包含着winsock.h文件,
如果你下次使用winsock2.h文件時,位置不對,然后編譯器會給你一大堆重定義錯誤問題。
初級解決辦法:
把winsock2.h文件放在任何可能包含winsock.h文件(尤其是windows.h文件,它就包含了winsock.h文件)的前面,因為winsock2.h頭文件有這樣的宏定義:
#ifndef _WINSOCK2API_
#define _WINSOCK2API_
#define _WINSOCKAPI_ /* Prevent inclusion of winsock.h in windows.h */
如果在winsock2.h之后再引用winsock.h頭文件,那么winsock.h文件並沒有什么卵用。
在生成應用程序時,即使不是MFC應用程序,也有有這個東西:
而網上對stdafx.h文件的解釋是:把一個工程(Project)中使用的一些MFC標准頭文件(如Windows.H、Afxwin.H)預先編譯,以后該工程編譯時,不再編譯這部分頭文件,僅僅使用預編譯的結果。這樣可以加快編譯速度,節省時間。
可怕的是它包含了windows.h文件,然而並不可怕的是:當我們使用AppWizard來自動生成某些項目的時候,系統會自動把所需要include的頭文件在stdafx.h中先include一下,這樣,我們只需要直接include這個stdafx.h文件即可。只在使用AppWizard來自動生成項目的時候,才出現.否則,就沒有必要include此頭文件stdafx.h了。參考網頁。
所以如果是MFC等windows窗口項目,需要把stdafx.h預編譯頭刪掉,否則其它應用刪不刪都無所謂了。
但是……但是……但是……即使我采取了以上辦法,並一一追蹤我自己寫的頭文件,看了看winsock.h和winsock2.h包含的先后關系,都滿足了winsock2.h在前的關系了,但是仍然有重定義,這個時候我看到另外一篇文章,里面提到【但當我在一個wxWidgets中調用它時,又出現那個讓人厭煩的錯誤 ““sockaddr”: “struct”類型重定義,明顯是wxWidgets先包含了windows.h,現在頭都大了,楞想不到怎么解決,在所有文件最開頭定義_WINSOCK2API_都沒用】,只想說呵呵了。人家要是愣是在最初給你先包含了windows.h文件(就譬如MFC中的stdafx.h頭文件),那你也沒轍了是吧。
終極辦法:
然而,天無絕人之路,終極辦法是:添加WIN32_LEAN_AND_MEAN宏定義,直接在vs的設置里預先添加這個宏定義就ok啦:
那么,這個奇怪的宏定義是干嘛的,查了一些資料后,是這么說的【 不加載MFC所需的模塊。在編譯鏈接時,以及在最后生成的一些供調試用的模塊時,速度更快,容量更小。】好多地方都是這么說的,就不給鏈接了,有興趣的自己搜搜這個宏吧。
然而,我仍然疑惑的是,我在哪里加載MFC所需的模塊了,其實我挺好奇上面那個圖中_WINDOWS這個宏是干嘛,但是暫時沒有搜到相關資料。
總結:其實大家也看到了,其實所謂的終極辦法也只能解決這種非MFC的應用程序的問題,至於其他情況出現這種問題的話,我還沒有去探索,畢竟還沒有遇到嘛。
感慨:下面這些選項在不了解情況的時候不要瞎選哈:
還有那個SDL檢查,個人建議不要選,因為windows上有它自己的一套_s的安全函數,否則,你就各種編譯不通過,還得改為它的_s(safe)函數,這個時候你要修改的東西多了。當然,這個sdl檢查還是有用的,畢竟人家的函數畢竟比較safe嘛,然而上次使用vsnprinf_s函數的時候,因為它提供額外參數問題,這個參數的錯誤導致我的程序里出現了莫名其妙的錯誤,都是淚。
要不是因為被要求使用vs做開發,我也不會去用它,個人還是鍾情於linux平台的東西。vs開發為了讓開發更簡單,更傻瓜式,它默默的幫你干了很多事情,等你出錯的時候,你就干瞪眼吧。也因為各種IDE的使用,很多程序員不了解整個編譯流程,總是習慣一鍵build。當然,各有各的好,各有各的適用情況,我個人偏好使用gcc罷了。