C++ sprintf 一个 LPCWSTR 变量
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3037850/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
sprintf an LPCWSTR variable
提问by Julio
I'm trying to debug print an LPCWSTR
string, but I get a problem during the sprintf
push in the buffer, because it retrieves only the first character from the string.
我正在尝试调试打印一个LPCWSTR
字符串,但在sprintf
推送缓冲区期间出现问题,因为它仅从字符串中检索第一个字符。
Here is the code:
这是代码:
HANDLE WINAPI hookedCreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) {
char buffer[1024];
sprintf_s(buffer, 1024, "CreateFileW: %s", lpFileName);
OutputDebugString(buffer);
return trueCreateFileW(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwFlagsAndAttributes, dwCreationDisposition, hTemplateFile);
}
For example I get CreateFileW: C
or CreateFileW: \
.
例如我得到CreateFileW: C
或CreateFileW: \
。
How do I properly push it into the buffer?
我如何正确地将它推入缓冲区?
Thank you.
谢谢你。
回答by Hans Passant
You need to tell sprintf() that you pass a wide character string. Use the %ls specifier:
您需要告诉 sprintf() 您传递了一个宽字符串。使用 %ls 说明符:
sprintf_s(buffer, 1024, "CreateFileW: %ls", lpFileName);
Do note how unproductive this is. Your code runs on a Unicode operating system. It must convert your char[] string back to a wide string before it can send it to the debugger. That's just wasted CPU cycles with a significant risk of data loss to boot. When you are in Rome, act like a Roman and use wchar_t + wsprintf(). And #define UNICODE so you'll automatically call the fast OutputDebugStringW(), the one that doesn't have to convert the string. The point of using C++ is to write fastcode, intentionally making is slow is pointless.
请注意这是多么徒劳。您的代码在 Unicode 操作系统上运行。它必须将您的 char[] 字符串转换回宽字符串,然后才能将其发送到调试器。这只是浪费了 CPU 周期,并且存在启动时数据丢失的重大风险。当你在罗马时,表现得像个罗马人,使用 wchar_t + wsprintf()。和#define UNICODE 这样你就可以自动调用快速的OutputDebugStringW(),它不需要转换字符串。用C++的重点是写快的代码,刻意写慢是没有意义的。
回答by shoosh
Use swprintf_swhich is the version of sprintf_s which is designed for wide-character strings.
使用swprintf_s,这是专为宽字符串设计的 sprintf_s 版本。
You'll also need an array of wchar_t
instead of char
and to use OutputDebugStringW()
您还需要一个数组wchar_t
代替char
和使用OutputDebugStringW()
Also, note you that swprintf_w
might not be entierly what you want to call. If it encounters a string that is longer than the size you give it, it executes some sort of assertion. I suggest you test this situation specifically.
另外,请注意,这swprintf_w
可能不是您想要调用的。如果它遇到一个比你给它的大小更长的字符串,它会执行某种断言。我建议你专门测试一下这种情况。
回答by Ofek Shilon
Unless you have a concrete reason to target unicode in this single function (and not, say, in your entire project), it might be wise to use charset-agnostic macros wherever possible:
除非你有一个具体的理由在这个单一的函数中(而不是在你的整个项目中)以 unicode 为目标,否则尽可能使用与字符集无关的宏可能是明智的:
HANDLE WINAPI hookedCreateFile(LPCTSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) {
TCHAR buffer[1024];
_stprintf_s(buffer, 1024, _T("CreateFileW: %s"), lpFileName);
OutputDebugString(buffer);
return trueCreateFile(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwFlagsAndAttributes, dwCreationDisposition, hTemplateFile);
}