c++ - 什么是 StringCbprintf,它与一般的 sprintf 有何不同?

标签 c++ c windows winapi printf

我正在查看以前编写的代码,我找到了 StringCbPrintf() 函数

我在 msdn 网站上找到这样的声明:

HRESULT StringCbPrintf(
  _Out_  LPTSTR pszDest,
  _In_   size_t cbDest,
  _In_   LPCTSTR pszFormat,
  _In_    ...
);

这里的_in__out_是什么?

为什么我们已经有了 sprintf() 还需要它?

最佳答案

_In__Out_ (注意:既不是您写的 _in_/_out _ ,也不是其他答案中写的带双下划线的 __In__/__Out__ )都是所谓的 SAL 注释。它们可以与 /analyze 一起使用编译器选项,并且可以帮助识别错误和问题,如缓冲区溢出等与原始 C 缓冲区和指针。除了MSDN documentation on SAL , 你也可以阅读这个 blog post .

有人讽刺地(而且错误地)写道:

"In the rest of the world, inputs are const pointers but I guess that was too simple. :)"

忽略了 SAL 比它更强大的事实。实际上,使用 SAL 还可以指定目标缓冲区的最大大小,指示哪个参数包含目标缓冲区大小;例如如果你打开<strsafe.h> header ,您可以阅读用于 StringCbPrintfW 的实际 SAL 注释(StringCbPrintf 的 Unicode 版本)是这样的:

STRSAFEAPI
StringCbPrintfW(
    __out_bcount(cbDest) STRSAFE_LPWSTR pszDest,
    __in size_t cbDest,
    __in __format_string STRSAFE_LPCWSTR pszFormat,
    ...)
{
    ....

请注意 __out_bcount(cbDest)应用于 pszDest 的 SAL 注释参数指定这是一个指向输出缓冲区(__out)的指针,大小字节(_bcount)表示参数 cbDest .如您所见,这是一个丰富注释(比简单的“const”或“非const”更丰富)。

在我看来,如果您使用健壮的容器类(如 std::vector)编写 C++ 代码,SAL 就有点没用了。或 std::string ,它知道自己的大小等。但是 SAL 在带有原始指针的 C-ish 代码中很有用(比如几个 Win32 API)。

关于你问题的第二部分:

"Why we need StringCbPrintf if we already have sprintf"

主要原因是sprintf是一个不安全和缓冲区容易溢出的函数;而不是 StringCbPrintf您必须指定目标缓冲区的最大大小,这有助于防止缓冲区溢出(这是安全敌人)。

关于c++ - 什么是 StringCbprintf,它与一般的 sprintf 有何不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13269146/

相关文章:

c++ - 除了共享库之外,g++ -fPIC 是否也适用于可执行文件?

c++ - C3867 : '_com_error::Description' : non-standard syntax; use '&' to create a pointer to member

c++ - 解释来自 OpenCV matchShapes() 的数字

c - struct tm->tm_yday 是否给出了正确的闰年值?

c - 为给定输入生成以下位掩码的最佳方法?

c++ - CryptEncrypt 不加密整个文本

c++ - 使用从另一个具体类返回的 shared_ptr

c++ - 如何进行文件 self 更新( native C++)

c++ - 使用来自不同线程的 postthreadmessage()

使用 printf 跨平台打印 64 位整数