从 Visual Studio 的哪个版本开始 vsnprintf 基本上符合标准?

2024-04-20

根据微软的文档vsnprintf https://msdn.microsoft.com/en-us/library/1kt27hek.aspx,至少从 2003 版 Visual Studio 开始,该函数就是 C(++) 运行时库的一部分。

int vsnprintf( char *buffer,        // Storage location for output
               size_t count,        // Maximum number of characters to write
               const char *format,  // Format specification
               va_list argptr )     // Pointer to list of other arguments

我问:哪些版本的 Visual Studio 是vsnprintf符合 C99 标准 (ISO/IEC 9899:1999) 的 x86 和 x64 捆绑 C(++) RTL 实现,假设

  • #define _CRT_SECURE_NO_WARNINGS之前执行#include <stdio.h>,这是现代版本的 Visual Studio RTL 所必需的;
  • if count大于零,那么buffer是一个指向(至少)的指针count可写字符;
  • 格式不是NULL并符合Microsoft 的格式规范语法 https://msdn.microsoft.com/en-us/library/56e442dc.aspx适用于 RTL 的特定版本;
  • 的价值count并且要生成的字符数都足够小以适应类型int;

我们希望一致性包括(除了标称输入的基本功能之外)这些要求(由标准的规范暗示)snprintf, which vsnprintf参考):

  1. 不产生未定义的行为(包括调用Microsoft 的无效参数处理程序 https://msdn.microsoft.com/en-us/library/ksazx244.aspx)在上述假设下;
  2. 返回要写入的长度(不包括终止空字符)buffer==NULL and count==0,从而允许飞行前确定输出的长度;
  3. 始终用终止空字符填充输出字符串buffer!=NULL and count>0并且返回的结果是非负的,包括由于小而截断的输出count.

注意以下comment https://stackoverflow.com/q/34996375/903600#comment57721538_34996375: 我愿意承认自己的不足restrict限定符仍然在大多数符合标准的允许范围内。


该文档对于 (3.) 的一致性不明确;据我所知,与 Visual Studio Community 2015 捆绑在一起的实现很好,但并非全部都是这样。

如果末尾有空间(即要写入的字符数小于count),缓冲区将以空终止。

该文档还明确暗示了这一点vsnprintf不符合 C99 标准的 (1.) 和 (2.) 时buffer==NULL and count==0;但文档的这些部分似乎是错误的:

如果要写入的字符数大于count,这些函数返回 -1 表示输出已被截断。

If buffer or format is NULL, or if count小于或等于零,这些函数调用无效参数处理程序


测试代码:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdarg.h>

int f( char *buffer,
       size_t count,
       const char *format,
       ...
     )
{
    va_list vArgs;
    int vRes;
    va_start(vArgs, format);
    vRes = vsnprintf( buffer, count, format, vArgs);
    va_end(vArgs);
    return vRes;
}

int main(void)
{
    char vBuf[6];
    int j, count;
#ifdef _MSC_VER
    printf("_MSC_VER = %ld\n",(long)(_MSC_VER));
#else
    printf("_MSC_VER is undefined\n");
#endif
    printf("f(NULL,0,\"%%d\",777):%3d\n", f(NULL,0,"%d",777));
    for(count=0 ;count<=sizeof(vBuf); ++count)
    {
        for(j=0; j<sizeof(vBuf)-1; ++j)
            vBuf[j] = '!';
        vBuf[j] = 0;
        j =  f(vBuf,count,"%d",777);
        printf("f(vBuf,%d,\"%%d\",777):%3d  vBuf: \"%s\"\n",count,j,vBuf);
    }
    return 0;
}

在我安装的 Visual Studio Community 2015 下提供

_MSC_VER = 1900
f(NULL,0,"%d",777):  3
f(vBuf,0,"%d",777):  3  vBuf: "!!!!!"
f(vBuf,1,"%d",777):  3  vBuf: ""
f(vBuf,2,"%d",777):  3  vBuf: "7"
f(vBuf,3,"%d",777):  3  vBuf: "77"
f(vBuf,4,"%d",777):  3  vBuf: "777"
f(vBuf,5,"%d",777):  3  vBuf: "777"
f(vBuf,6,"%d",777):  3  vBuf: "777"

并在安装了 Visual Studio 2008 后(我相信 SP1 + PSDK 7.1)

_MSC_VER = 1500
f(NULL,0,"%d",777):  3
f(vBuf,0,"%d",777): -1  vBuf: "!!!!!"
f(vBuf,1,"%d",777): -1  vBuf: "7!!!!"
f(vBuf,2,"%d",777): -1  vBuf: "77!!!"
f(vBuf,3,"%d",777):  3  vBuf: "777!!"
f(vBuf,4,"%d",777):  3  vBuf: "777"
f(vBuf,5,"%d",777):  3  vBuf: "777"
f(vBuf,6,"%d",777):  3  vBuf: "777"

请注意缺少终止空字符,特别是count==3,即使输出为正。


您现在提到的页面给出了答案:

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

你的输出是一致的_vsnprintf https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/vsnprintf-vsnprintf-vsnprintf-l-vsnwprintf-vsnwprintf-l:

如果要写入的字符数小于或等于 count,则 _vsnprintf 和 _vsnwprintf 函数都返回写入的字符数;如果要写入的字符数大于 count,这些函数将返回 -1,表示输出已被截断。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

从 Visual Studio 的哪个版本开始 vsnprintf 基本上符合标准? 的相关文章

随机推荐

  • 访问设备配置变量

    在我的 Rails 应用程序中 直接从视图访问 Devise 配置变量的方法是什么 我想展示config allow unconfirmed access for来自设计的 confirmable模块 该变量设置在devise rb初始化器
  • 当应用程序进入后台时(之前)iOS 拍摄的屏幕截图?

    希望大家都了解一下iOS在应用程序进入后台之前截取屏幕截图 我从那里得到的官方文件 http developer apple com library ios DOCUMENTATION iPhone Conceptual iPhoneOSP
  • 为什么我不能在 try 块内定义之前使用 Javascript 函数?

    正如所讨论的here https stackoverflow com questions 261599 why can i use a function before its defined in javascript 函数定义可以在定义之
  • 用于复制和重命名文件的 GitHub Action

    有没有一个聪明的方法copy and rename通过 GitHub Actions 文件 我想将一些自述文件复制到 docs文件夹 相同的存储库 而不是远程存储库 它们将根据其 frontmatter 在其中重命名title 目标是拥有某
  • Python-插入ms访问表

    我可以通过某些查询从 ms 访问中获取一些数据 但我无法将数据存储到任何表中 例如 import sys os pyodbc conn str r DRIVER Microsoft Access Driver mdb accdb r DBQ
  • 以编程方式禁用 UIButton 单击时的突出显示

    一定有办法做到这一点 但我找不到 我有一个以编程方式创建的按钮 UIButton button UIButton buttonWithType UIButtonTypeRoundedRect button frame CGRectMake
  • 使用 stargazer 添加一行注释

    我想运行一些回归并使用 stargazer 创建一个表 例如 linear 1 lt lm rating complaints privileges learning raises critical data attitude linear
  • C语言中有“设计模式”吗? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 升级到 MT 4.0 后不显示索引 TableView

    升级到 MT 4 0 后 以前在右侧边框上显示索引的 TableView 不再工作 表视图仍按部分显示并正常工作 但未显示索引 我在 UITableViewSource 中定义了这三种方法 并且这三种方法似乎都有效 public overr
  • 表更新事件处理程序

    我正在研究 AX 2012 中新委托和事件订阅模式的功能 目前我希望检测特定字段何时被修改 例如何时SalesTable SalesStatus更改为SalesStatus Invoiced 我创建了以下事件后处理程序并附加到 SalesT
  • 如何从 SQLAlchemy 映射对象中发现表属性

    我有一个与表映射的类 在我的例子中是以声明的方式 我想从这个类中 发现 表属性 列 名称 关系 engine create engine sqlite databasePath echo True setting up root class
  • virtualenv ImportError:没有名为 urllib3 的模块

    我在ubuntu上安装了virtualenv 但是 当我尝试创建 virtualenv 时 出现错误 我的 Zenv 文件夹不包含 activate 我该如何修复它 我会经常这样做 这是我第一次收到此错误 ubuntu ip 172 31
  • 从打包序列中获取每个序列的最后一项

    我试图通过 GRU 放置打包和填充的序列 并检索每个序列最后一项的输出 当然我的意思不是 1项目 但实际上是最后一个 未填充的项目 我们预先知道序列的长度 因此应该很容易为每个序列提取length 1 item 我尝试了以下方法 impor
  • 如何获取资产文件夹中图像的字符串路径

    我需要向第三方库传递存储在我的资产文件夹中的图像的路径 我读过一些答案 但没有一个有帮助 我努力了file android asset uk jpg但它不起作用 我需要向第三方库传递存储在我的资产文件夹中的图像的路径 没有路 您的资产不是文
  • 宁静的路线和 Django

    我正在将 Rails 项目迁移到 Django 中 Rails 项目是使用 Restful 路线构建的 它从不接触数据库 相反 它只是重定向到不同的方法 这些方法都使用指定的操作方法调用外部服务 现在 我已经找到了许多 django 框架
  • 渲染 selectManyCheckbox 而不使用 HTML 表

    有没有办法从渲染的html中删除由创建的表格h selectManyCheckbox服务器面孔中的标签 我正在使用 twitter bootstrap 并将复选框放置在下拉菜单中 ul class dropdown menu dropdow
  • Innosetup - 在安装开始之前引用[Code]中的文件

    这是一种延续这个问题 https stackoverflow com questions 5658488 adding a help button to an innosetup wizard page 我想将一个文件包含在我的安装包中 C
  • 在 Swift 中以编程方式创建 UITableViewController

    正如标题所示 我试图以编程方式设置 UITableViewController 经过几个小时的尝试 我希望有人可以帮助我 是的 我已经查看了有关此事的其他帖子 import UIKit class MainViewController UI
  • 导出为 pdf 在 ggplot2 中无法正确显示

    我有一个由 Fig NPK 和 Barchart fert 组成的复杂图形 P 它们是使用数据表 Fert 制作的 列包括 Vil N P 和 K 我的目标是创建一个pdf文件并使用ghostscript在pdf文件中嵌入 Times Ne
  • 从 Visual Studio 的哪个版本开始 vsnprintf 基本上符合标准?

    根据微软的文档vsnprintf https msdn microsoft com en us library 1kt27hek aspx 至少从 2003 版 Visual Studio 开始 该函数就是 C 运行时库的一部分 int v