页首Html代码

返回顶部

wchar_t 宽字符集 研究 和COM的 BSTR VARIANT

 

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");
};
posted @ 2012-09-06 00:30  ayanmw  阅读(3089)  评论(0编辑  收藏  举报

页脚Html代码