我正在查看以前编写的代码,我找到了 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 havesprintf
"
主要原因是sprintf
是一个不安全和缓冲区容易溢出的函数;而不是 StringCbPrintf
您必须指定目标缓冲区的最大大小,这有助于防止缓冲区溢出(这是安全敌人)。
关于c++ - 什么是 StringCbprintf,它与一般的 sprintf 有何不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13269146/