VC++ 6.0中关于UNICODE和_UNICODE的问题总结
来源:互联网 发布:公司软件开发外包 编辑:程序博客网 时间:2024/06/05 03:43
在TCHAR.H头文件中总体的结构如下:
以上可以看到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环境下使用的。
/* 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环境下使用的。
0 0
- VC++ 6.0中关于UNICODE和_UNICODE的问题总结
- _UNICODE和UNICODE的区别
- Windows编程中UNICODE和_UNICODE定义问题
- Windows编程中UNICODE和_UNICODE定义问题
- Windows编程中UNICODE和_UNICODE定义问题
- Windows编程中UNICODE和_UNICODE定义问题
- vc 内的 UNICODE _UNICODE 区别
- vc 中关于Unicode的一些总结
- UNICODE和_UNICODE的区别和联系
- VC++的Unicode编程(宏UNICODE与_UNICODE)
- VC++的Unicode编程(宏UNICODE与_UNICODE)
- VC++的Unicode编程(宏UNICODE与_UNICODE)
- UNICODE和_UNICODE
- Unicode和_UNICODE
- 关于宽字符(_UNICODE||UNICODE)和windows套接(socket)字编程问题
- VC中, 关于UNICODE的L和_T()
- UNICODE,_UNICODE
- 关于VC多字节字符集和unicode宽字符集的使用和问题(转)
- Java 语言实现折半查找(二分查找)
- Aircrack-ng 学习笔记
- 在 PyQt4 中的菜单和工具栏¶
- 2015年蓝桥杯省赛B组C/C++(试题+答案)
- [Java]多线程之同步及死锁
- VC++ 6.0中关于UNICODE和_UNICODE的问题总结
- 判断百度地图及高德地图是否安装
- [Struts2官方指南的个人学习和翻译] Struts2的配置元素-请求处理元素
- hdu 单词数 (set)
- BASH BUG:cve-2014-6271验证与利用
- hdu 5203 Rikka with wood sticks
- Linux 命令 集锦
- java的反射机制
- hdu-2200 Eddy's AC难题