在初学Windows网络编程时,曾经遇到过两类编译错误(VC6的Build窗口哗哗的显示了102个Errors),都是些类型未定义或者重复定义问题,让我感到很郁闷。这两种错误情况下的第一条错误信息分别为:
错误情形1:mswsock.h(69) : error C2065: 'SOCKET' : undeclared identifier
错误情形2:winsock2.h(99) : error C2011: 'fd_set' : 'struct' type redefinition
后来,我静下心来仔细分析一下错误提示及相关文件,终于找到了原因。
我们知道,Windows网络编程至少需要两个头文件:winsock2.h和windows.h,而在WinSock2.0之前还存在一个老版本的winsock.h。正是这三个头文件的包含顺序,导致了上述问题的出现。
先让我们看看winsock2.h的内容,在文件开头有如下宏定义:
#ifndef _WINSOCK2API_
#define _WINSOCK2API_
#define _WINSOCKAPI_ /* Prevent inclusion of winsock.h in windows.h */
_WINSOCK2API_ 很容易理解,这是最常见的防止头文件重复包含的保护措施。_WINSOCKAPI_的定义则是为了阻止对老文件winsock.h的包含,即是说,如果用户先包含了winsock2.h就不允许再包含winsock.h了,否则会导致类型重复定义。这是怎样做到的呢?很简单,因为winsock.h的头部同样存在如下的保护措施:
#ifndef _WINSOCKAPI_
#define _WINSOCKAPI_
再回过头来看winsock2.h,在上述内容之后紧跟着如下宏指令:
/*
* Pull in WINDOWS.H if necessary
*/
#ifndef _INC_WINDOWS
#include <windows.h>
#endif /* _INC_WINDOWS */
其作用是如果用户没有包含windows.h(_INC_WINDOWS在windows.h中定义)就自动包含它&#