【问题标题】:Can vsnprintf return negative value of magnitude greater than 1?vsnprintf 可以返回大于 1 的负值吗?
【发布时间】:2012-02-23 21:43:24
【问题描述】:

vsnprintf() 可以返回一个大于 1 的负值吗?如果有,在什么情况下会这样做?

我尝试使用 %ls 作为 char 数组的格式说明符,并尝试复制比分配的数组更大的内容。在这两种情况下,我都得到 -1 作为返回值。

【问题讨论】:

    标签: c c-libraries


    【解决方案1】:

    是的,它可以,就像“它被允许”一样。具体情况取决于您的平台,并且没有以任何方式指定或监管。与返回值有关的唯一可移植的事情是检查它是否有 < 0 以查看是否有错误。

    来自标准(7.21.6.12(3),vsnprintf):

    以空结尾的输出已被完全写入当且仅当返回值为非负数且小于n

    任何给定的平台当然可以对返回值做出额外的保证;请查阅您的文档。

    【讨论】:

    • 哦,我实际上并不知道它是一个 C 标准库函数,我有一种(错误)它是 Microsoft 特有的印象。
    • 我正在使用 gcc。在 gcc 中可以吗?
    • @Knight71:我现在怎么办?检查 glibc 源,这应该很容易找到。
    • @Knight71:您为什么对vsnprintf() 返回不同负数的可能性如此感兴趣?仅检查小于零的返回值是可移植的,我不确定通过查找特定的负数会获得什么。注意:缓冲区太小不会返回“错误”,它会返回大于或等于缓冲区大小的非负数(表示输出被截断)。
    • 我对它很感兴趣,因为 nLen += vsnprintf(&bExpandBuff[nLen], BUFF_LEN - nLen, Msg, arglist); 行可能存在错误。
    【解决方案2】:

    C99 标准说:

    §7.19.6.12 vsnprintf 函数

    #include <stdarg.h>
    #include <stdio.h>
    int vsprintf(char *restrict s, size_t n, const char *restrict format, va_list arg);
    

    说明

    ¶2 vsnprintf 函数等价于 snprintf,带有变量参数列表 替换为arg,它应该由va_start 宏初始化(和 可能是后续的va_arg 电话)。 vsnprintf 函数不会调用 va_end 宏。245) 如果复制发生在重叠的对象之间,则行为是 未定义。

    返回

    ¶3 vsnprintf 函数返回将被写入的字符数 n 是否足够大,不包括终止空字符或负数 发生编码错误时的值。因此,空终止输出已 当且仅当返回值为非负且小于n时才完全写入。

    245) 作为函数 vfprintfvfscanfvprintfvscanfvsnprintfvsprintfvsscanf调用va_arg宏,返回后arg的值是不确定的。

    而且,由于它是根据snprintf() 定义的,所以这是该部分:

    §7.19.6.5 snprintf 函数

    #include <stdio.h>
    int snprintf(char *restrict s, size_t n, const char *restrict format, ...);
    

    说明

    ¶2 snprintf 函数等价于fprintf,只是输出被写入 一个数组(由参数s 指定)而不是流。如果n 为零,则不写入任何内容, s 可能是一个空指针。否则,n-1st 之外的输出字符是 丢弃而不是写入数组,最后写入一个空字符 实际写入数组的字符数。如果复制发生在对象之间 重叠,行为未定义。

    返回

    ¶3 snprintf 函数返回将被写入的字符数 n 是否足够大,不包括终止的空字符或负数 发生编码错误时的值。因此,空终止输出已 当且仅当返回值为非负且小于n 时才完全写入。


    它并没有说它会在错误时返回-1;只是任何负值。所以是的,允许在错误上给出一个幅度大于 1 的负值。


    微软的版本

    请注意,Microsoft 针对 Visual Studio 2015 的 vsnprintf 规范说:

    vsnprintf 返回写入的字符数,不包括终止的空字符。返回值 -1 表示发生了编码错误。如果由 count 指定的缓冲区大小不足以包含由 format 和 argptr 指定的输出,则 vsnprintf 的返回值是在 count 足够大的情况下将写入的字符数。如果返回值大于 count - 1,则输出已被截断。

    _vsnprintf_vsnwprintf 如果要写入的字符数小于或等于 count,则返回写入的字符数;如果要写入的字符数大于 count,则这些函数返回 -1,表示输出已被截断。所有函数的返回值都不包括终止的空值,如果写入的话。

    请注意,情况并非总是如此:

    从 Visual Studio 2015 和 Windows 10 中的 UCRT 开始,vsnprintf 不再与 _vsnprintf 相同。 vsnprintf函数符合C99标准;保留_vnsprintf 是为了向后兼容。

    为了比较,Visual Studio 2013 documentation 说:

    vsnprintf_vsnprintf_vsnwprintf如果要写入的字符数小于等于count,则返回写入的字符数;如果要写入的字符数大于 count,则这些函数返回 -1,表示输出已被截断。返回值不包括终止的空值,如果写了一个。

    snprintf() 的可比较页面是:

    【讨论】:

      猜你喜欢
      • 2021-09-21
      • 2013-08-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-28
      • 1970-01-01
      • 2013-02-06
      • 2021-05-07
      相关资源
      最近更新 更多