当前位置: 首页 > 图文教程 > 开发语言 > VC++ > 宽字符标量L"xx"在VC6.0/7.0和GNU g++中的不同实现

VC++
用VC++创建自定义向导程序
自定义 CRichEditCtrl 控件
Office 2000 风格的停泊、智能型菜单
黑客攻击手段之偷梁换柱
完善 CPopupText 类
让工具条显示256色图像
定制编辑框的上下文菜单
列表控件排序功能的实现
一个优秀的网格控件CGridCtrl
如何用代码动态添加控件
如何在编辑框中使用IAutoComplete接口
应用程序中添加“Coolbars”的简单方法
介绍一个有Toolbar功能的可重用类 CPopupText
在工具栏按钮上添加文本标签
类似Dreamweaver的颜色选择器
如何设置ListView控件的完全行(Full Row)选项
如何enable/disable菜单项
关于CEdit控件的透明 --作者:monsoon
动态菜单项、状态条提示、工具条提示问题
CAnimateCtrl::Open的使用问题

VC++ 中的 宽字符标量L"xx"在VC6.0/7.0和GNU g++中的不同实现


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-10-30   浏览: 43 ::
收藏到网摘: n/a

宽字符标量L"xx"在VC6.0/7.0和GNU g++中的不同实现

作者:乾坤一笑

  锲子:本文源于在 VCKBASE C++ 论坛和周星星大哥的一番讨论,这才使我追根索源,找到了理论依据和实践的证明。(本文一些资料和测试代码由周星星提供)

《The C++ Programming Language 3rd》中有这么两段话:

from 4.3:
A type wchar_t is provided to hold characters of a larger character set such as Unicode. It is a distinct type. The size of wchar_t is implementation-defined and large enough to hold the largest character set supported by the implementation’s locale (see §21.7, §C.3.3). The strange name is a leftover from C. In C, wchar_t is a typedef (§4.9.7) rather than a builtin type. The suffix _ t was added to distinguish standard typedefs.

from 4.3.1:
Wide character literals are of the form L′ab′, where the number of characters between the quotes and their meanings is implementation-defined to match the wchar_t type. A wide character literal has type wchar_t.

这两段话中有两个要点是我们关心的:

  1. wchar_t 的长度是由实现决定的;
  2. L"ab" 的含义是由实现决定的。

那么GNU g++和VC6.0/7.0各是怎么实现的呢?看下面代码:

//author: **.Zhou#include <stdio.h>#include <stdlib.h>#include <windows.h>void prt( const void* padd, size_t n ){ const unsigned char* p = static_cast<const unsigned char*>( padd ); const unsigned char* pe = p + n; for( ; p<pe; ++p ) printf( " %02X", *p ); printf( "\n" );}int main(){ char a[] = "VC知识库"; wchar_t b[] = L"VC知识库"; prt( a, sizeof(a) ); prt( b, sizeof(b) ); system( "Pause" ); // 说明: // Dev-CPP4990 显示为: // 56 43 D6 AA CA B6 BF E2 00 // 56 00 43 00 D6 00 AA 00 CA 00 B6 00 BF 00 E2 00 00 00 // VC++6.0 和 VC.net2003 显示为: // 56 43 D6 AA CA B6 BF E2 00 // 56 00 43 00 E5 77 C6 8B 93 5E 00 00 // 可见,Dev-CPP中的L""不是unicode编码,只是简单的扩充,汉字需要4bytes存储 HWND h = FindWindow( NULL, "计算器" ); SetWindowTextA( h, a ); system( "Pause" ); SetWindowTextW( h, b ); system( "Pause" ); // 说明: // VC++6.0 和 VC.net2003 都能成功将标题改为"VC知识库" // 而 Dev-CPP4990 只有 SetWindowTextA 显示正确,而 SetWindowTextW 显示的是乱码 } 
  这段代码说明了,g++(Dev-CPP 用的是 MingGW 编译器)中 L"xx" 解释为把作为 non-wide-char 的 "xx" 扩展为作为 wide-char 的 wchar_t,不足则在高位补0;而 VC6.0 的 L"xx" 解释为把作为 MBCS 的 "xx" 转换为作为 unicode 的 WCHAR,目前的 MBCS 是以 char 为一个存储单元的,而 WCHAR 在 winnt.h 中定义为 typedef wchar_t WCHAR。在 Windows 平台上,只要是超过 0~127 范围内的 char 型字符,都被视为 MBCS,它由1到2个字节组成,MBCS 字符集跟它的地区代码页号有关。在某个特定的 Windows 平台,默认的代码页号可以在控制面板 -> 区域选项中设定。

关于上述结论可以有下面这个程序来验证:
//author: smileonce#include <stdio.h>#include <stdlib.h>#include <assert.h>#include <windows.h>void prt( const void* padd, size_t n ){ const unsigned char* p = static_cast<const unsigned char*>( padd ); const unsigned char* pe = p + n; for( ; p<pe; ++p ) printf( " %02X", *p ); printf( "\n" );}int main(){ char a[] = "VC知识库"; wchar_t b[] = L"VC知识库"; prt( a, sizeof(a) ); prt( b, sizeof(b) ); PSTR pMultiByteStr = (PSTR)a; PWSTR pWideCharStr; int nLenOfWideCharStr; // 利用API函数MultiByteToWideChar()来把a转化成unicode字符 nLenOfWideCharStr = MultiByteToWideChar( CP_ACP, 0, pMultiByteStr, -1, NULL, 0); pWideCharStr = (PWSTR)HeapAlloc( GetProcessHeap(), 0, nLenOfWideCharStr * sizeof(WCHAR) ); assert( pWideCharStr ); MultiByteToWideChar( CP_ACP, 0, pMultiByteStr, -1,