这是在64位机器上加上unicode字符串的整数值的正确大小吗?或者我错过了什么?
DWORD errorMessageID = GetLastError();
const wchar_t msgFmt[] = L"foo baaa. Error code = %d";
wchar_t bufferMsg[sizeof(msgFmt) + // room for fmt message string itself
21 + // enough to hold numbers up to 64-bits
sizeof(wchar_t) // byte-terminattor
];
int nBytesWritten = swprintf_s(bufferMsg,
msgFmt,
sizeof(msgFmt),
errorMessageID);
MessageBox(NULL,
bufferMsg,
TEXT("Copy to clipboard failed"),
MB_OK | MB_ICONERROR);
答案 0 :(得分:2)
除了传递给Kirill Kobelev's answer中提到的swsprintf_s()
的参数的问题之外,还有至少一些不太正确的事情,即使并非所有事情都会导致缺陷:
DWORD
为32位,即使在构建64位目标时也是如此。保留21个字符进行格式化是一个小小的过度杀伤,但不是一个bug。但是,这表明存在可能导致其他问题的误解。DWORD
是无符号类型,因此使用“%d”格式化它是不对的答案 1 :(得分:1)
不,这不正确。正确的代码应如下所示:
const wchar_t msgFmt[] = L"foo baaa. Error code = %d";
wchar_t bufferMsg[sizeof(msgFmt)/sizeof(wchar_t) + // room for fmt message string itself
21 + // enough to hold numbers up to 64-bits
1 // symbol-terminator
];
int nBytesWritten = swprintf_s(bufferMsg,
sizeof(bufferMsg)/sizeof(wchar_t),
msgFmt,
errorMessageID);
在这两种情况下,您都使用了字节大小而不是元素数量加上params的顺序是错误的。您调用MessageBox()
函数是正确的。
答案 2 :(得分:0)
手动计算sprintf
呼叫目标所需的缓冲区大小很难维护。让系统为您执行计算更容易,更安全。 Visual Studio附带的CRT为此提供了_scprintf
系列函数。
以下代码说明了它的用法。它实现了一个函数,它接受一个格式字符串和可变数量的参数,并返回一个格式化结果的字符串:
std::wstring FormatString( const wchar_t* a_Format, ... ) {
std::wstring text;
va_list argList;
va_start( argList, a_Format );
// Calculate required buffer size
size_t size = _vscwprintf( a_Format, argList ) + 1;
va_end( argList );
if ( size > 0 ) {
// Dynamically construct buffer with the correct size
std::vector<wchar_t> buffer( size );
va_start( argList, a_Format );
int count = _vsnwprintf_s( buffer.data(), size, size - 1,
a_Format, argList );
va_end( argList );
if ( count >= 0 ) {
// Construct return value
text = std::wstring( buffer.data(), count + 1 );
}
}
return text;
}
此函数返回std::wstring
个对象。就像实现中使用的std::vector
一样,它会自动为您管理内存,并且不需要明确的清理代码。要将其与需要LPCWSTR
参数的Windows API调用一起使用,请调用其c_str()
成员。
在原始代码中使用此功能会将其浓缩为以下内容:
DWORD errorMessageID = GetLastError();
MessageBoxW(NULL,
FormatString( L"foo baaa. Error code = %u", errorMessageID ).c_str(),
L"Copy to clipboard failed",
MB_OK | MB_ICONERROR);