http://www.cppblog.com/lapcca/archive/2010/05/06/114649.html
Unicode与Ansi是两种不同的编码方式标准,Ansi中的字符采用8bit,而Unicode中的字符采用16bit。
(对于字符,Ansi以单字节存放英文字符,以双字节存放中文等字符;而Unicode下,英文和中文的字符都以双字节存放)
Unicode码也是一种国际标准编码,采用二个字节编码,与Ansi码不兼容。目前,在网络、Windows系统和很多大型软件中得到应用。
8bit的ANSI编码只能表示256种字符,表示26个英文字母是绰绰有余的,但是表示汉字等有着成千上万个字符的非西方字符肯定就不够了,正是如此才引入Unicode标准。
在软件开发中,特别是使用C语言的一些有关字符串处理的函数,Ansi和Unicode是区分使用的,那么Ansi类型的字符和Unicode类型的字符如何定义,如何使用呢?Ansi和Unicode又如何转换呢?
一.定义部分
Ansi:即char
Unicode:即wchar_t
注意:VC++6.0 默认编码方式为Ansi,.Net默认编码方式为Utf-16,Linux GCC默认编码方式为utf-8
二.可用函数
Ansi:可用字符串处理函数:strcat(),strcpy(),strlen()等以str打头的函数
Unicode:可用字符串处理函数:wcscat(),wcscpy(),wcslen()等以wcs打头的函数。
三.系统支持
Windows 98:只支持AnsiWindows 2000/XP/2003:既支持Ansi又支持Unicode
Windows CE:只支持Unicode。
说明:
1> 在COM里面只支持UNICODE。
2> Windows 2000整个OS系统都是基于Unicode的,为此在windows 2000 下使用ANSI是需要付出代价的,虽然在编码上不用任何的转换,但是这种转化是隐藏的,是占用系统资源的(CPU,内存)
四.如何区分:
在我们软件开发中往往需要即支持Ansi又支持Unicode,不可能在要求类型转换的时候,重新改变字符串的类型,和使用于字符串上的操作函数。为此,标准C运行期库和Windows 提供了宏定义的方式。
在C语言里面提供了 _UNICODE宏(有下划线),在Windows里面提供了UNICODE宏(无下划线)
只要定了_UNICODE宏和UNICODE宏,系统就会自动切换到UNICODE版本,否则,系统按照ANSI的方式进行编译和运行。
只定义了宏并不能实现自动的转换,还需要一系列的字符定义支持
1. TCHAR
如果定义了Unicode宏,则TCHAR被定义为wchar_t。
typedef wchar_t TCHAR;
否则TCHAR被定义为char
typedef char TCHAR;
2.LPTSTR
如果定义了Unicode宏,则LPTSTR被定义为LPWSTR
typedef LPTSTR LPWSTR;
否则TCHAR被定义为char
typedef LPTSTR LPSTR;
补充一下:
utf -8是可以用于真正的流式传输的,Unicode是一种编码方案
( utf -8是Unicode的一种具体实现。类似的实现还有utf-16等等 )
三.Ansi/Unicode字符和字符串
TChar.h是String.h的修改,用于创建Ansi/Unicode通用字符串。
Unicode字符串的每个字符都是16位的。
wchar_t是Unicode字符的数据类型。
附:有部分Unicode函数也可以在Win9X中使用,但可能会出现意想不到错误。
所有的Unicode函数均以wcs开头,Ansi函数均以str开头;ANSI C规定C运行期库支持Ansi和Unicode
Ansi:
#include <string.h>
char * strcat(char *, const char *)
char * strchr(cons char *, int)
int strcmp(const char *, const char *)
char * strcpy(char *, const char *)
size_t strlen(const char *)
Unicode:
#include <stdlib.h>
wchar_t * wcscat(wchar_t *, const wchar_t *)
wchar_t * wcschr(const wchar_t * , int)
int wcscmp(const wchar_t *, const wchar_t *)
wchar_t * wcscpy(wchar_t *, const wchar_t *)
wchar_t wcslen(const wchar_t *)
L" wash " : 用于将ANSI字符串转换为Unicode字符串;
_TEXT(" wash ")根据是否定义Unicode或_Unicode进行转换。
附:_Unicode用于C运行库;Unicode用于Windows头文件。
ANSI/Unicode通用数据类型:
1> Both(ANSI/Unicode)
LPCTSTR、LPTSTR、PCTSTR、PTSTR、TBYTE(TCHAR)
2> ANSI
LPCSTR、LPSTR、PCSTR、PSTR、CHAR
3> Unicode
LPCWSTR、LPWSTR、PCWSTR、PWSTR、WCHAR (与ANSI相比,多了' W ')
字符表示意义如下:
L表示long指针、P表示这是一个指针、C表示是一个常量、T表示在Win32环境中, 有一个_T宏、STR表示这个变量是一个字符串
在设计dll时最好提供Anis和Unicode函数,Ansi函数只用于分配内存,将字符转换为Unicode字符,然后调用Unicode函数。
最好使用操作系统函数,少使用或不实用C运行期函数
eg:操作系统字符串函数(shlWApi.h)
StrCat(), StrChr(), StrCmp(), StrCpy()等
注意它们区分大小写,也区分ANSI和Unicode版本
附:Ansi版函数在原函数后加大写字母A
Unicode函数在原函数后加大写字母W
成为符合Ansi和Unicode的函数:
1> 将文本串视为字符数组,而不是chars数组或字节数组
2> 将通用数据类型(如TCHAR和PTSTR)用于文本字符和字符串
3> 将显式数据类型(如BYTE和PBYTE)用于字节、字节指针和数据缓存
4> 将TEXT宏用于原义字符和字符串
5> 修改字符串运算问题
如:sizeof(szBuffer) -> sizeof(szBuffer) / sizeof(TCHAR)
malloc(charNum) -> malloc(charNum * sizeof(TCHAR))
对Unicode字符操作的函数还有:(也有ANSI和Unicode版本)
lstrcat() , lstrcmp() / lstrcmpi()[ 它们在内部调用CompareString() ], lstrcpy(), lstrlen()
这些是作为宏实现的。
C运行期函数
tolower();
toupper();
isalpha();
islower();
isupper();
print();
windows函数
PTSTR CharLower(PTSTR pszString);
PTSTR CharUpper(PTSTR pszString);
BOOL IsCharAlpha(TCHAR ch);
BOOL ISCharAlphaNumeric(TCHAR ch);
BOOL IsCharLower(TCHAR ch);
BOOL IsCharUpper(TCHAR ch);
wsprintf();
转换Buffer:
DWORD CharLowerBuffer(PTSTR pszString , DWORD cchString);
DWORD CharUpperBuffer(PTSTR pszString , DWORD cchString);
转换单个字符,如:
TCHAR cLowerCaseChar = CharLower((PTSTR)szString[0]);
确定字符是ANSI或Unicode:
BOOL IsTextUnicode(
const VOID * pBuffer, //待检查的InputBuffer
int cb, //InputBuffer中的长度
LPINT lpi //检查选项
)
附:此函数在Win9x系统中,没有实现代码,始终返回FALSE
五、Unicode与ANSI之间的转换:
( 1 ) 使用宏定义
如下例:
- char szA[40];
- wchar szW[40];
- //Normal sprintf: all string are Ansi
- sprintf(szA , "%s", "ANSI str");
- //Convert Unicode to ANSI
- sprintf(szA, "%S", L"Unicode str");
- //Normal swprintf: all string are unicode
- swprinf(szW, "%s", L" Unicode str");
- // Convert ANSI to Unicode
- swprinf( szW, L"%S", "Ansi str");
( 2 ) 使用MultiByteToWideChar()
该函数映射一个字符串到一个宽字符( Unicode )的字符串。
( 3 ) 使用WideCharToMultiByte()
映射一个宽字符串到一个多字节字符串。