程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> VC >> 關於VC++ >> 寬字符標量L"xx"在VC 6.0/7.0和GNU g++中的不同實現

寬字符標量L"xx"在VC 6.0/7.0和GNU g++中的不同實現

編輯:關於VC++

锲子:本文源於在 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》。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved