首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >dprintf的跨平台兼容性

dprintf的跨平台兼容性
EN

Stack Overflow用户
提问于 2010-01-21 22:45:41
回答 3查看 10.4K关注 0票数 5

Linux有一个很好的函数dprintf

dprintf()vdprintf()函数(如glibc2库中所示)与fprintf()vfprintf()完全类似,只不过它们输出到文件描述符fd而不是给定的流。

然而,正如同一消息来源所指出的:

这些函数是GNU扩展,而不是C或POSIX。很明显,名字选错了。许多系统(如MacOS)都有名为dprintf()的不兼容函数,通常是printf()的一些调试版本,例如

代码语言:javascript
复制
void dprintf (int level, const char *format, ...);

其中第一个参数是调试级别(输出到stderr)。此外,dprintf() (或DPRINTF)也是调试printf的流行宏名称。因此,可能最好在可移植的程序中避免此功能。

我的问题

如果dprintf存在,我如何创建一个可以安全地调用它的设置,或者如果该函数不存在,就无法使用一些合理合理的错误消息进行编译?我想我会这样做:

代码语言:javascript
复制
#ifdef SOMETHING
    #define Dprintf dprintf
#else
    #error "no dprintf"
#endif

但我不知道SOMETHING应该是什么。我想我可以把它限制在Linux上,但我能让它变得更宽松吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2010-01-22 00:15:26

看起来dprintf()实际上是在POSIX.1-2008中(具有您想要的语义),所以您可以这样做:

代码语言:javascript
复制
#if !defined(__GLIBC__) && _POSIX_C_SOURCE < 200809
#error "dprintf may not exist, or may be wrong"
#endif

如果使用的是gnu系统,则定义__GLIBC__。这可能是最安全的,你可以不写一个小的测试程序。

票数 9
EN

Stack Overflow用户

发布于 2010-01-21 23:53:43

如果您正在为构建系统使用autotools,则可以进行autoconf测试。

代码语言:javascript
复制
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也有它。

代码语言:javascript
复制
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*指针即可。

票数 4
EN

Stack Overflow用户

发布于 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()

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2113539

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档