分享
 
 
 

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

王朝vc·作者佚名  2006-01-17
窄屏简体版  字體: |||超大  

宽字符标量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.

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

wchar_t 的长度是由实现决定的;

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, pWideCharStr, nLenOfWideCharStr );

prt( pWideCharStr, nLenOfWideCharStr * sizeof(WCHAR) );

system( "Pause" );

// // 说明:

// 56 43 D6 AA CA B6 BF E2 00 //char a[] = "VC知识库";

// 56 00 43 00 E5 77 C6 8B 93 5E 00 00 //wchar_t b[] = L"VC知识库";

// 56 00 43 00 E5 77 C6 8B 93 5E 00 00 //用MultiByteToWideChar()把a转换为unicode

// // 可见,b[]的字符代码就是unicode代码

return 0;

}

呵呵,问题已经明了,总结一下:

ISO C 中 wchar_t 是一个 typedef,ISO C++ 中 wchar_t 是语言内建的数据类型,L"xx" 是ISO

C/C++ 语言内建的表示 wchar_t 的文本量的语法;

wchar_t 的长度是由实现决定的;

L"xx" 的意义是由实现决定的;

默认的 "xx" 是 non-wide-char,其每个元素数据的类型是 char;与其相对应的 L"xx"

是wide-char,其每个元素数据的类型是wchar_t。

为什么 C/C++ 语言把 L"xx" 定义为由实现决定的呢?这显然是为了 C/C++ 的普适性、可移植性。Bjarne

的观点认为,C++ 的方式是允许程序员使用任何字符集作为串的字符类型。另外,unicode

编码已经发展了若干版本了,是否能永久适合下去也不得而知。有关 unicode 的详细论述以及和其它字符集的比较,我推荐你看《无废话xml》

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有