如何将Win32 <tchar.h>中的TCHAR字符串转换为UTF-8字符串?
无需依赖区域设置的TCHAR转UTF-8方案
由于TCHAR的实际类型由项目的UNICODE/_MBCS宏决定,我们可以直接调用Windows原生API完成转换,全程不依赖区域设置,完美适配DLL场景:
核心思路
Windows API提供的WideCharToMultiByte和MultiByteToWideChar函数,通过指定编码页CP_UTF8,可以精准控制转换目标为UTF-8,完全避开区域设置的影响。
情况1:UNICODE模式(TCHAR = wchar_t)
直接将宽字符转换为UTF-8多字节字符串:
#include <windows.h> #include <tchar.h> #include <stdlib.h> char* TCHARToUTF8(const TCHAR* tstr) { if (!tstr) return NULL; // 获取所需UTF-8缓冲区大小 int utf8Len = WideCharToMultiByte(CP_UTF8, 0, tstr, -1, NULL, 0, NULL, NULL); if (utf8Len == 0) return NULL; // 分配内存(调用者需用free()释放) char* utf8Str = (char*)malloc(utf8Len * sizeof(char)); if (!utf8Str) return NULL; // 执行转换 WideCharToMultiByte(CP_UTF8, 0, tstr, -1, utf8Str, utf8Len, NULL, NULL); return utf8Str; }
情况2:ANSI模式(TCHAR = char)
先将ANSI编码的TCHAR转换为宽字符,再转成UTF-8:
#include <windows.h> #include <tchar.h> #include <stdlib.h> char* TCHARToUTF8(const TCHAR* tstr) { if (!tstr) return NULL; // 获取宽字符缓冲区大小 int wideLen = MultiByteToWideChar(CP_ACP, 0, tstr, -1, NULL, 0); if (wideLen == 0) return NULL; wchar_t* wideStr = (wchar_t*)malloc(wideLen * sizeof(wchar_t)); if (!wideStr) return NULL; // ANSI转宽字符 MultiByteToWideChar(CP_ACP, 0, tstr, -1, wideStr, wideLen); // 宽字符转UTF-8 int utf8Len = WideCharToMultiByte(CP_UTF8, 0, wideStr, -1, NULL, 0, NULL, NULL); if (utf8Len == 0) { free(wideStr); return NULL; } char* utf8Str = (char*)malloc(utf8Len * sizeof(char)); if (!utf8Str) { free(wideStr); return NULL; } WideCharToMultiByte(CP_UTF8, 0, wideStr, -1, utf8Str, utf8Len, NULL, NULL); free(wideStr); return utf8Str; }
通用兼容版本(自动适配宏定义)
通过预编译宏合并两种情况,适配不同项目设置:
#include <windows.h> #include <tchar.h> #include <stdlib.h> char* TCHARToUTF8(const TCHAR* tstr) { if (!tstr) return NULL; #ifdef UNICODE int utf8Len = WideCharToMultiByte(CP_UTF8, 0, tstr, -1, NULL, 0, NULL, NULL); if (utf8Len == 0) return NULL; char* utf8Str = (char*)malloc(utf8Len * sizeof(char)); if (!utf8Str) return NULL; WideCharToMultiByte(CP_UTF8, 0, tstr, -1, utf8Str, utf8Len, NULL, NULL); return utf8Str; #else int wideLen = MultiByteToWideChar(CP_ACP, 0, tstr, -1, NULL, 0); if (wideLen == 0) return NULL; wchar_t* wideStr = (wchar_t*)malloc(wideLen * sizeof(wchar_t)); if (!wideStr) return NULL; if (!MultiByteToWideChar(CP_ACP, 0, tstr, -1, wideStr, wideLen)) { free(wideStr); return NULL; } int utf8Len = WideCharToMultiByte(CP_UTF8, 0, wideStr, -1, NULL, 0, NULL, NULL); if (utf8Len == 0) { free(wideStr); return NULL; } char* utf8Str = (char*)malloc(utf8Len * sizeof(char)); if (!utf8Str) { free(wideStr); return NULL; } WideCharToMultiByte(CP_UTF8, 0, wideStr, -1, utf8Str, utf8Len, NULL, NULL); free(wideStr); return utf8Str; #endif }
注意事项
- 转换后的字符串由
malloc分配内存,调用者必须使用free释放,避免内存泄漏。 - 若转换失败,函数返回
NULL,可通过GetLastError()获取具体错误码排查问题。 - DLL中调用这些Windows API无需修改区域设置,不会影响宿主程序的locale状态。
- 确保项目的
UNICODE/_MBCS宏定义与TCHAR的实际类型匹配。
内容的提问来源于stack exchange,提问作者Dan Shelton
相关产品推荐
相关产品推荐

