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

2016-01-29 12:16 15 1 收藏

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

【 tulaoshi.com - C语言心得技巧 】

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

作者:乾坤一笑

(本文来源于图老师网站,更多请访问https://www.tulaoshi.com)

  锲子:本文源于在 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.

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

(本文来源于图老师网站,更多请访问https://www.tulaoshi.com) wchar_t 的长度是由实现决定的; L"ab" 的含义是由实现决定的。

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

//author: **.Zhou#include <stdio.h#include <stdlib.h#include <windows.hvoid 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.hvoid 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,
                        

来源:https://www.tulaoshi.com/n/20160129/1485342.html

延伸阅读
虽然关于Java字符串“==”和“equals”的问题是Java学习中的最基础的一个问题,但是仍然有不少刚刚学习Java的同学搞不清楚里面的原理,最近和朋友讨论到这个问题,所以写篇文章给大家分享一下我自己的理解。 首先让我们看一个例子: 代码如下:     public class TestStringEquals {       ...
俗话说"工欲善其事,必先利其器",我使用vc6.0已经有一段时间了.慢慢的摸索出了一些可是说是技巧的东东吧(有些也许是从书上,网上看来的,忘记了).我想这些技巧对大家来说都比较实用. 1.当程序代码格式乱七八糟的时候怎么办?你可以自己慢慢的用TAB,SPACE,去调整,如果是一个成千上万行的可就够你受的了.其实你可以先选中你想调整的代码,然后在"edi...
标签: Web开发
在程序语言中定义的各种各样的数据类型中,我们都会为其定义一个"空值"或"假值",比如对象类型的空值null,.NET Framework中数据库字段的空值DBNull,boolean类型的假值false等等。在JavaScript中也有很多种的"空值"和"假值",那么它们都有什么共同点和不同点呢?     其实标题里面我已经列出了JavaScript中所有的"...
标签: 养生 健康
适量饮茶,好处很多。如果饮茶过浓,饮茶时间,方法不合适,不同体质的人选用一样的饮茶方法,或用茶水送部分药等,不仅是起不到好作用,反而于身体不利。自古来,我国人民对喝茶是很讲究。在饮茶生活中对时间、浓淡、冷热、新陈以及不同的人如何饮茶等都有丰富经验。前人总结不同时间、不同情况下饮茶的作用是不一样的,如早茶使人心情愉...
标准C++规定new一个对象时如果分配内存失败就应抛出一个std::bad_alloc异常,如果不希望抛出异常而仅仅传回一个NULL指针,可以用new的无异常版本:new(nothrow)。 VC6.0在new头文件中声明了这两种operator new操作符: void *__cdecl operator new(size_t) _THROW1(std::bad_alloc); void *__cdecl operator new(size_t, const std::no...

经验教程

69

收藏

18
微博分享 QQ分享 QQ空间 手机页面 收藏网站 回到头部