VC++ 6.0中关于UNICODE和_UNICODE的问题总结

在TCHAR.H头文件中总体的结构如下:
/* For backwards compatibility */为了向后的兼容性
#ifdefine  _UNICODE     //如果定义了_UNICODE标识符,字符或字符串则按照宽字符集进行编码
#ifdef  __cplusplus
}    /* ... extern "C" */
#endif    /* __cplusplus */


/* ++++++++++++++++++++ UNICODE ++++++++++++++++++++ */

#include  <wchar.h>     //包含宽字符头文件

#ifdef  __cplusplus
extern  "C"  {
#endif    /* __cplusplus */

#ifndef  _WCTYPE_T_DEFINED
typedef  unsigned  short  wint_t  ;
typedef  unsigned  short  wctype_t  ;
#define  _WCTYPE_T_DEFINED
#endif    /* _WCTYPE_T_DEFINED */

#ifndef  __TCHAR_DEFINED
typedef  wchar_t        _TCHAR ;
typedef  wchar_t        _TSCHAR ;
typedef  wchar_t        _TUCHAR ;
typedef  wchar_t        _TXCHAR ;
typedef  wint_t         _TINT ;
#define  __TCHAR_DEFINED
#endif    /* __TCHAR_DEFINED */

 

#define  __T  ( x  )       L  ##  x           //将x字符或字符串按照宽字符进行存储,L表示宽字符,##表示L和x字符中间没有空格被称为"令牌粘贴"。
.
.
#define  _tcslen            wcslen        //将求宽字符长度的函数定位_tcslen

.
#define  _tprintf           wprintf      //将宽字符输出函数定义为_tprintf

...
#define  _tscanf            wscanf      //将宽字符输入函数定义为_tscanf

.
.
#else                         //以下就是在没有定义_UNICODE标识符的时候,字符或字符串将按照ASCIII编码方式存储或者多字节字符集进行存储


/* ++++++++++++++++++++ SBCS and MBCS ++++++++++++++++++++ */

#ifdef  __cplusplus
}    /* ... extern "C" */
#endif    /* __cplusplus */

#include  <string.h>                  //包含字符串头文件

#ifdef  __cplusplus
extern  "C"  {
#endif    /* __cplusplus */


#define  _TEOF          EOF

#define  __T  ( x  )       x                    //  _T将字符或者字符串x按照单字节字符存储



/* Program */

#define  _tmain         main
#define  _tWinMain      WinMain
#define  _tenviron     _environ
#define  __targv        __argv


/* Formatted i/o */

#define  _tprintf           printf                     //将_tprintf按照printf函数进行输出


#define  _tscanf          scanf                           //将_tscanf   按照 scanf函数进行输入


/* "logical-character" mappings */

#define  _tcsclen           strlen                        //将_tcslen按照strlen来求得字符串的长度 
#define  _tcscnlen          strnlen
...
..
#endif


以上就是TCHAR.H为兼容UNICODE字符集而定义的头文件,头文件整体结构可以归纳为
#ifdef  _UNICODE
     将通用函数解释为处理宽字符的函数 ;
#else
     将通用函数解释为处理单字节字符的函数或者说是处理ASCII码字符的函数;
#endif
-------------------------------------------------------------------------
-------------------------------------------------------------------------
和定义_UNICODE不同的是,在头文件WinUser.h(主要包含用户界面函数)中,如果定义了标识符UNICODE。

WINUSERAPI
int
WINAPI
MessageBoxA (
     _In_opt_  HWND  hWnd ,
     _In_opt_  LPCSTR  lpText ,
     _In_opt_  LPCSTR  lpCaption ,
     _In_  UINT  uType );
WINUSERAPI
int
WINAPI
MessageBoxW (
     _In_opt_  HWND  hWnd ,
     _In_opt_  LPCWSTR  lpText ,
     _In_opt_  LPCWSTR  lpCaption ,
     _In_  UINT  uType );
#ifdef UNICODE
#define  MessageBox     MessageBoxW
#else
#define  MessageBox     MessageBoxA
#endif  // !UNICODE
 ..下面很多还有同样的定义


//如果定义了UNICODE标识符,则MessageBox()函数将按照MessageBoxW()进行解析输出,即按照宽字符进行输出。否则按照MessageBoxA()函数进行输出,即按照ASCII码或多字节字符集进行输出 。



-------------------------------------------------------------------------------------------
问题就来了:
在Microsoft Visual Studio 6.0开发环境中,如果使用MessageBox()函数,比如下列程序:

#include<windows.h>
#include<tchar.h>

int 
WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdline, int iShowCmd)
{
     MessageBox(NULL, _T("Hello Windows NT!"),_T("HelloMsg"),MB_YESNOCANCELL);
     return 0;
}

1、在”工程项目“中设置属性,C/C++选项下的Preprocessor definition中,默认是按照多字节字符集进行编码的如图,即没有定义_UNICODE和UNICODE,所以_T(x)将按照x进行编码存储,即按照ASCII码。    MessageBox将按照MessageBoxA()进行输出,即按照ASCII码。 所以他们的编码表是一致的,所以输出正常。

2、如果在 Preprocessor definition中添加UNICODE或者_UNICODE中的任何一个则上面的程序就出现乱码或者显示不完全的现象。
   如果添加UNICODE:
     则MessageBox将按照MessageBoxW进行输出,即宽字符输出,但是_T(x)由于没有定义_UNICODE,所以依然按照ASCII进行编码即为x,两个字码表不一致           
     所以就会出现乱码。
   如果添加_UNICODE:(注意前面有下划线)
     则MessageBox()将按照MessageBoxA进行输出,即ASCII或多字节字符集,但是_T(x)会按照L##x,即宽字符进行编码,即一个字符占用两个字节,低字节在前,高字节在后,所以在输出字符时候,比如编码为0x0041,而存储的顺序则为0x41,0x00,所以MessageBox再按照ASCII码进行输出时只会输出一个字符而把0x00当做字符串结束标识。所以最终只会输出一个字符。
     
因此在VC++6.0中需要将两个同时添加到里面才会显示正常,如图。

相比vs以后产品,比如vs2010,vs2013中,字符集中的”使用UNICODE字符集“,则表示已经同时将两个标识符添加到里面了。




以上可以看到UNICODE和_UNICODE的区别,_UNICODE的定义是在tchar.h头文件中,这个头文件并不是ANSI C标准的一部分,所以其中定义的每一个函数和宏都有一个下划线前缀。也就是说在在非windows环境下同样可以使用,而UNICODE是定义在头文件WinUser.h头文件中,这个头文件是windows中的一个重要头文件,windows中重要的头文件有:windef.h   winnt.h  winbase.h   winuser.h   wingdi.h 。  所以UNICODE是windows环境下使用的。
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页