在MacOS/Linux上替换MS _vscprintf的方法?

18

作为一次学习经验,我正在将一些东西从Windows移植到MacOS,并遇到了类似于这样的问题:

void SomeClass::someFunction(const char* format, va_list args)
{
    int size = _vscprintf(format, args); // length after formatting
    std::string s;
    s.resize(size);
    vsprintf(&s[0]);
    ...
}

现在,由于_vscprintf是Microsoft特有的,在Linux上我没有找到类似的东西,所以我想在这里问一下。

同时,让我们假设这段代码处于某个关键路径中,不应该有额外的堆分配或类似的开销。

在MacOS/Linux上,推荐使用什么替代_vscprintf呢?

谢谢!


1
与此问题可能重复:_vscprintf在Android上的等效物是什么? - ismail
可能没有直接替代 _vscprintf 函数的方法;但是如果您将其与 vsprintf 一起使用(如在 someFunction 示例中),则可以改用 asprintf 函数(如果该函数在您的系统上可用)。 - oliver
2个回答

25

你可以使用 vsnprintf 替代;

  int _vscprintf (const char * format, va_list pargs) { 
      int retval; 
      va_list argcopy; 
      va_copy(argcopy, pargs); 
      retval = vsnprintf(NULL, 0, format, argcopy); 
      va_end(argcopy); 
      return retval; 
   }

感谢@dbasic提供了更完整的解决方案,感谢@j-a纠正了明显的错误。


同上。不仅如此,这样做的合理期望是崩溃。 - jheriko
应该使用vsnprintf(NULL, 0, f, a);代替(这恰好是Daniel上面列出的问题的答案)。 - dash-tom-bang
我想要补充的一件事是,必须使用va_copy来复制a,否则在后续的函数调用中它将无法工作。我在Mac OS X上遇到了这样的问题。 - doptimusprime
3
我是这么做的: int _vscprintf (const char * format, va_list pargs) { 复制一份参数列表argcopy; 利用vsnprintf函数,将格式化后的字符串输出到NULL指针,返回需要的字符数赋值给retval; 结束argcopy参数列表; 返回retval。 } - doptimusprime
有人测试过这个吗?最好的做法似乎是创建一个初始缓冲区,将其作为vsnprintf的第一个参数传递,然后... - allicoder

14

之前的解决方案是可以的,但存在两个错误:

  1. va_copy函数只有一个参数而不是两个参数。
  2. 调用vsnprintf函数时没有使用argcopy变量;如果再次调用vsnprintf函数,会导致堆栈损坏。
int _vscprintf (const char * format, va_list pargs)
{ 
    int retval; 
    va_list argcopy;
    va_copy(argcopy, pargs); 
    retval = vsnprintf(NULL, 0, format, argcopy); 
    va_end(argcopy); 
    return retval;
}

您不应该在缩进中放置除代码或注释以外的任何内容。 - Daniel Larsson
1
通常情况下,当你将一个va_list传递给一个函数时,假设它会被调用的函数“消耗掉”。va_copy()代码通常应该在问题中的SomeClass::someFunction()中,而不是在库函数中。唯一安全的调用库函数的方式是使用va_list的副本。我在MS手册页面(http://msdn.microsoft.com/en-us/library/w05tbk72%28v=vs.110%29.aspx和http://msdn.microsoft.com/en-us/library/t32cf9tb%28v=vs.110%29.aspx)上没有看到任何其他说明。 - Jonathan Leffler

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接