便携式的方式把标准输出在二进制模式

我正在编写用作cgi的C程序来生成和输出gif图像。 它们用于HTML页面,标签格式为<img src="/cgi-bin/gifprogram.cgi?param=val&etc"> ,其中查询stringparams描述了由cgi生成的图像。

C程序cgi的调用像这样将其输出发送到标准输出。 在这种情况下,输出是一个包含大量二进制(不可打印)字节的gif图像。 这在Unix / Linux上已经很好了。 但Windows显然需要一个单独的不可移植的_setmode(_fileno(stdout),_O_BINARY)调用(以及一些特定于Windows的#include )。 否则,你会得到通常的cr / lf问题,即每个0x0A之前都有一个假0x0D。 这在gif中看起来不太好

有没有任何可移植的方法解决这个问题,使用ANSI标准的C没有任何特定于平台的语法,没有很多#ifdef东西来尝试检测Windows编译环境? 此外,一些Windows编译器显然使用_setmode(_fileno(stdout),_O_BINARY)而其他人使用setmode(fileno(stdout),O_BINARY) ,我也必须尝试检测。

>>编辑<<在回复评论中…

多谢你们。 我显然必须采取一些完全posix兼容/便携式的程序,并与他们混为一谈,只是为了窗口[编者注:JoNaThAn:真的,不需要编辑大写:),我个人的写作风格是故意的语法松散]。

以下是我正在考虑介绍的一些愚蠢行为。 似乎工作,据我所知,使用mingw。 这是否足够,即对全部或大部分其他编译器有效? 这是否有必要,即任何简洁而又快捷的方式,用较less的/可读的代码行来完成同样的事情?

 /* --- * windows-specific header info * ---------------------------- */ #ifndef WINDOWS /* -DWINDOWS not supplied by user */ #if defined(_WINDOWS) || defined(_WIN32) || defined(WIN32) \ || defined(DJGPP) /* try to recognize windows compilers */ \ || defined(_USRDLL) /* must be WINDOWS if compiling for DLL */ #define WINDOWS /* signal windows */ #endif #endif #ifdef WINDOWS /* Windows opens stdout in char mode, and */ #include <fcntl.h> /* precedes every 0x0A with spurious 0x0D.*/ #include <io.h> /* So emitcache() issues a Win _setmode() */ /* call to put stdout in binary mode. */ #if defined(_O_BINARY) && !defined(O_BINARY) /* only have _O_BINARY */ #define O_BINARY _O_BINARY /* make O_BINARY available, etc... */ #define setmode _setmode #define fileno _fileno #endif #if defined(_O_BINARY) || defined(O_BINARY) /* setmode() now available */ #define HAVE_SETMODE /* so we'll use setmode() */ #endif #if defined(_MSC_VER) && defined(_DEBUG) /* MS VC++ in debug mode */ /* to show source file and line numbers where memory leaks occur... */ #define _CRTDBG_MAP_ALLOC /* ...include this debug macro */ #include <crtdbg.h> /* and this debug library */ #endif #define ISWINDOWS 1 #else #define ISWINDOWS 0 #endif 

而后续相应的代码确保stdout是二进制模式

  #if ISWINDOWS /* compiling for win... */ #ifdef HAVE_SETMODE /* try to use setmode()*/ if ( setmode ( fileno (stdout), O_BINARY) /* to set stdout */ == -1 ) /* handle error here*/ ; /* to binary mode */ #else /* setmode not available */ #if 1 /* so try this...*/ freopen ("CON", "wb", stdout); /* freopen stdout binary */ #else /* or maybe this... */ stdout = fdopen (STDOUT_FILENO, "wb"); /*fdopen stdout binary*/ #endif /* done */ #endif /* " */ #endif /* " */ 

你会注意到我试图build议setmode()的select。 虽然我的替代testing还没有成功,但我已经留下了语法以备将来参考,以防万一其中一些最终certificate有用。