Linux有一个很好的函数dprintf。
dprintf()和vdprintf()函数(如glibc2库中所示)与fprintf()和vfprintf()完全类似,只不过它们输出到文件描述符fd而不是给定的流。
然而,正如同一消息来源所指出的:
这些函数是GNU扩展,而不是C或POSIX。很明显,名字选错了。许多系统(如MacOS)都有名为
dprintf()的不兼容函数,通常是printf()的一些调试版本,例如
void dprintf (int level, const char *format, ...);其中第一个参数是调试级别(输出到
stderr)。此外,dprintf()(或DPRINTF)也是调试printf的流行宏名称。因此,可能最好在可移植的程序中避免此功能。
我的问题
如果dprintf存在,我如何创建一个可以安全地调用它的设置,或者如果该函数不存在,就无法使用一些合理合理的错误消息进行编译?我想我会这样做:
#ifdef SOMETHING
#define Dprintf dprintf
#else
#error "no dprintf"
#endif但我不知道SOMETHING应该是什么。我想我可以把它限制在Linux上,但我能让它变得更宽松吗?
发布于 2010-01-22 00:15:26
看起来dprintf()实际上是在POSIX.1-2008中(具有您想要的语义),所以您可以这样做:
#if !defined(__GLIBC__) && _POSIX_C_SOURCE < 200809
#error "dprintf may not exist, or may be wrong"
#endif如果使用的是gnu系统,则定义__GLIBC__。这可能是最安全的,你可以不写一个小的测试程序。
发布于 2010-01-21 23:53:43
如果您正在为构建系统使用autotools,则可以进行autoconf测试。
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*指针即可。
发布于 2010-01-21 23:46:46
Autoconf测试可以检查dprintf(1, "blablabla")是写到stdout还是stderr,dprintf(-1, "blablabla")是以有趣的方式失败还是写到stderr。
如果libc为您提供了错误的dprintf(),您可以在snprintf() (甚至更好的asprintf())和write()之上实现它。然后向链接器提到你的“dprintf.o”,这样它就更喜欢你的链接器而不是libc。
如果你想要一个更好的名字,我建议fdprintf()。
https://stackoverflow.com/questions/2113539
复制相似问题