Вы можете сделать тест autoconf, если вы используете autotools для вашей системы сборки.
AC_LANG([C])
AC_USE_SYSTEM_EXTENSIONS
AC_ARG_WITH([dprintf],
[AS_HELP_STRING([--with-dprintf],
[Assume that dprintf prints to a specified file descriptor])],
[], [with_dprintf=check])
AS_IF([test "x$with_dprintf" = xcheck],
[AC_RUN_IFELSE(
[AC_LANG_PROGRAM([[
#include <stdio.h>
#include <string.h>
int debug_level;
]], [[
char msg[] = "Hello, world!\n";
char rcv[sizeof(msg)] = "";
FILE *f = tmpfile();
int fd = fileno(f);
debug_level = fd - 1;
dprintf(fd, "%s", msg);
fseek(f, 0, SEEK_SET);
fread(rcv, 1, sizeof(msg), f);
return strcmp(msg, rcv);
]]
)], [with_dprintf=yes])])
AS_IF([test "x$with_dprintf" = xyes],
[AC_DEFINE([HAVE_DPRINTF], [1],
[dprintf prints to a specified file descriptor])])
(с учетом --with-dprintf
или --without-dprintf
при кросс-компиляции, поскольку AC_RUN_IFELSE
в этих случаях недопустимо.)
fdopen не соответствует стандарту C, но равно в POSIX.2 и более поздних версиях. Я не помню ни одного UNIX-подобного, в котором бы его не было - черт, даже в Windows это есть.
int fdprintf(int fd, char *fmt, ...) {
va_list ap;
FILE *f = fdopen(fd);
int rc;
va_start(ap, &fmt);
rc = vfprintf(f, fmt, ap);
fclose(f);
va_end(ap);
return rc;
}
Конечно, если вы знаете, в какой дескриптор файла вы будете печатать, просто оставьте вместо него указатель FILE*
.