wchar_t 是和 char 平等的地位,即 wchar_t 并非 typedef出来的,是原生的变量。
简单的说,它拥有两个字节,和short 占用空间一样。
比如:
字符串 "我们\n"
ANSI 的十六进制为:ce d2 c3 c7 0A 00
6个字节,其中包括字符串最后的\0
Unicode十六进制为:11 62 EC 4E 0A 00 00 00
8个字节,所有的字符 全部是2个字节,即使字母 数字 都是,当然换行\n 也是0A 00 了。
一般 程序中字符串 前面加个 L"" 就表示 是Unicode 字符串了。
windows下有一个 宏 _T("") 和上面的一样。
1.第一个简单的问题,如何打印出来 Unicode?
2个字节,可以按照 数字打印,但是如果要按照字符 打印,用普通的printf 是不行了。
可以使用wprintf打印,也就是 普通的 printf前面加一个 Wide的 W。类似的函数都是,比如 wsprintf。
char* lpszText = "我们\r\n";//ANSI:ce d2 c3 c7
//Unicode:11 62 EC 4E
//回车 \r 0D \n 0A
printf("char * text: %s 0x%08x 0x%08x \nANSI编码是 :", lpszText, lpszText, *lpszText );
print_hex_to_file(stdout,(const uint8_t *)lpszText,strlen(lpszText)+1,16);//此函数自己编写的
BSTR bstrText = _com_util::ConvertStringToBSTR(lpszText);
wprintf(L"BSTR text: %s 0x%08x 0x%08x \nUniCode编码是:", bstrText, bstrText, *bstrText);
print_hex_to_file(stdout,(const uint8_t *)bstrText,wcslen(bstrText)*2+2,16);
的结果为:
char * text: 我们
0x013fbd80 0xffffffce
ANSI编码是 :0x ce d2 c3 c7 0d 0a 00
BSTR text: 我们
0x007be5b4 0x00006211
UniCode编码是:0x 11 62 ec 4e 0d 00 0a 00 00 00
对了,开始我用wprintf始终无法打印中文,后来 添加了下面的两句 才可以了。
#include <locale.h>
setlocale( LC_CTYPE, "chs" );
源码的编码 是 ANSI 或 UniCode 对结果 都没有什么影响。
对了 如果要打印单个 wchar_t 怎么打印呢?上面都是指针,都是字符串,那好好办。单个。。。
setlocale( LC_CTYPE, "chs" );
WCHAR wstr1;
wchar_t wstr2;
wstr1=L'我';
wstr2=L'们';
wprintf(L"我们 在宽字符集(%c,%c) 的每个大小为:%d 字节\n",wstr1,wstr2,sizeof(wstr1));
赋值的时候 始终记住 L ,结果正常。
我们 在宽字符集(我,们) 的每个大小为:2 字节
如果你将 '我' 赋值给 一个 char 类型,那么 你只能得到 '我' ce d2 的 前一个 字节。打印出来 肯定 就是乱码 ? 了。
char ss;
ss='我';
printf("ss=%c\n",ss);
结果是:
ss=?
并且 ? 后面是没有换行的,因为 \n 已经和 %c 融合 为 ? 了。。反正 ce 打印出来 或许 很诡异的。
2.第二个简单的问题,如何 与 char 类型 互相转换
int ConvertStringToBSTRDemo()
{
char* lpszText = "Test";
printf("char * text: %s\n", lpszText);
BSTR bstrText = _com_util::ConvertStringToBSTR(lpszText);
wprintf(L"BSTR text: %s\n", bstrText);
::SysFreeString(bstrText);
return 0;
};
int ConvertBSTRToStringDemo()
{
BSTR bstrText = ::SysAllocString(L"Test");
wprintf(L"BSTR text: %s\n", bstrText);
char* lpszText2 = _com_util::ConvertBSTRToString(bstrText);
printf("char * text: %s\n", lpszText2);
::SysFreeString(bstrText);
delete[] lpszText2;
return 0;
};
这个全局函数 SysFreeString() 发现 不加 貌似 也没有内存泄漏?(VLD检测)
我靠,我知道了,可能是VLD没有重载COM里的内存分配释放,所以 还是 去掉 SysFreeString前的注释。
经过实验 循环10 000 000次,会发生 300MB左右的内存泄漏。但是VLD确实无法检测。所以 千万得小心了!
COM编程里的 BSTR其实就是wchar_t* 类型,有BSTR的地方就是分配了指针的,一定要自己释放内存的!
BSTR和String(char *) 的转换,其实就是 wchar_t* 和 char * 的转换了。这是COM的方法
还可以使用stdlib里的方法:
wcstombs 和 mbstowcs wcs应该就是WideCString ,但是 mbs 怎么就表示 ansi普通的字符编码 我就不知道缩写了
wchar_t ws[10]; //sizeof(ws)=20字节
wsprintf(ws,L"我们");
char cs[50];
sprintf(cs,"");
//清除数据 与初始化
//wchar_t * 转化为 char *
int ret=0;
printf("wcstombs前: cs=%4s ws=%%S=%S\n",cs,ws);
ret=wcstombs(cs,ws,sizeof(ws));
printf("wcstombs后: ret=%d,cs=%4s ws=%%S=%S\n",ret,cs,ws);
wsprintf(ws,L"");
//清除数据 与初始化
//char * 转化为 wchar_t *
wprintf(L"mbstowcs前: ws=%4s cs=%%S=%S\n",ws,(cs));
ret=mbstowcs(ws,cs,sizeof(ws)*2);
wprintf(L"mbstowcs后: ret=%d,ws=%2s cs=%%S=%S\n",ret,ws,(cs));
运行结果
wcstombs前: cs= ws=%S=我们
wcstombs后: ret=4,cs=我们 ws=%S=我们
mbstowcs前: ws= cs=%S=我们
mbstowcs后: ret=2,ws=我们 cs=%S=我们
windows下也有另外的相同意思的API
//MultiByteToWideChar
最后 加上 我喜欢的 print_hex_to_file函数
void print_hex_to_file(FILE*fp,const uint8_t *array, int count/*aray的大小*/,int lineCount/*默认应该是16*/)
{
int i;
fprintf(fp,"0x ");
for(i = 0; i < count; ){
fprintf(fp,"%02x ", array[i]);
i++;
if ( !(i % lineCount) && i<count){
fprintf (fp,"\n0x ");
}
}
fprintf(fp,"\n");
};