【问题标题】:Why is vsnprintf Not Writing the Same Number of Characters as strncpy Would?为什么 vsnprintf 写入的字符数与 strncpy 不同?
【发布时间】:2019-06-05 16:44:00
【问题描述】:

我问过the same question about strncpy,但string 最终包含整个输入字符串。将字符串传递给vsnprintf 时,最后一个字符总是被截断:https://rextester.com/UIQMX91570

为简单起见,我还在代码中内嵌了上面的实时示例链接:

void bar(const char* format, va_list vlist) {
    const auto buf_size = vsnprintf(nullptr, 0U, format, vlist);
    string buffer(buf_size, '\0');

    vsnprintf(data(buffer), buf_size, format, vlist);
    cout << data(buffer) << endl;
}

void foo(const char* format, ...) {
    va_list vlist;

    va_start(vlist, format);
    bar(format, vlist);
    va_end(vlist);
}

如果我用:foo("lorem ipsum %d", 13) 调用它,我得到的输出是:

lorem ipsum 1

如我所料:lorem ipsum 13

谁能解释这个差异?当我调试时,我得到一个 14 的 buf_size 应该足以包含整个字符串,但它没有:(

【问题讨论】:

  • 解释一下答案,为了strncpy 粉丝的利益:strncpy 可以产生无效的 C 字符串(没有 nul 终止符); vsnprintf 不能。

标签: c++ printf variadic-functions string-length strncpy


【解决方案1】:

因为手册页清楚地说明了这一点

如果输出由于此限制而被截断,则返回值是在有足够空间可用的情况下将写入最终字符串的字符数(不包括结尾的 '\0')。

如果您检查第二个vsnprintf 调用的返回值,您会看到返回值等于大小,如手册页所示:

因此,大小或更大的返回值意味着输出是 被截断。

【讨论】:

    【解决方案2】:

    谁能解释这个差异?

    因为他们记录的行为不同。

    strncpy()

    如果在复制整个数组 src 之前达到 count,则生成的字符数组不是以 null 结尾的

    但是vsnprintf()

    最多写入 buf_size-1 个字符。 生成的字符串将以空字符结尾,除非 buf_size 为零。

    重点是我的。

    【讨论】:

      【解决方案3】:

      vsnprintfbuf_size 参数指定要写入多少个字符,包括终止 NUL 字符。返回值是产生的字符数,不包括终止 NUL 字符。

      你想要

      const auto buf_size = vsnprintf(nullptr, 0U, format, vlist) + 1;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-10-26
        • 1970-01-01
        • 2016-09-07
        • 1970-01-01
        • 2010-11-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多