Try to put the any code which requires OS preprocessor directives into subroutines so that the code that contains preprocessor directives is not normally visible. That way you only need see the preprocessor ridden code when you need to edit it directly.
I guess what I'm saying is create a sort of platform specific level in your code which hides the implementation of OS specific code where-ever possible. Does wonders for readability and keeps all those preprocessor directives hidden away.
I normally have a platform.h header file which I include in all my .cpp files which contains a lot of platform specific defines and includes.
Here's an example of a simple platform.h that supports sockets.
Code:
#ifndef _INCLUDED_PLATFORM_H_
#define _INCLUDED_PLATFORM_H_
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <windows.h>
#define ERRNO (WSAGetLastError())
typedef int socklen_t;
#else
typedef int SOCKET;
#include <errno.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#define wsprintf sprintf
#define closesocket(s) close(s)
#define ERRNO errno
#define stricmp(x,y) strcasecmp(x,y)
#define strnicmp(x,y,z) strncasecmp(x,y,z)
#endif
#ifndef INADDR_NONE
#define INADDR_NONE 0xffffffff
#endif
#ifndef INADDR_ANY
#define INADDR_ANY 0
#endif
#ifndef SHUT_RDWR
#define SHUT_RDWR 2
#endif
#endif // INCLUDED__PLATFORM_H_
Hope that helps.
-Daniel