首先,这是一个字符集的问题。在ANSI字符集中,字符类型是char,在UNICODE字符集中,字符类型是wchar_t,也可以称之为宽字符,宽字符占两个字节。
然后,我们来看一段定义代码:
//winnt.h
typedef char CHAR; //8位
typedef wchar_t WCHAR; //16位
typedef CHAR *PCHAR;
typedef CHAR *PSTR;
typedef CONST CHAR *PCSTR;
typedef WCHAR *PWCHAR;
typedef WCHAR *PWSTR;
typedef CONST WCHAR *PCWSTR;
//重点在这边
#ifdef UNICODE //如果使用的事UNICODE字符集,一般来说,VS建立的工程默认都是使用UNICODE字符集
typedef WCHAR TCHAR,*PTCHAR,*PTSTR;
typedef CONST WCHAR *PCTSTR;
#define _TEXT(quote) L##quote
#define _T(quote) L##quote
#else
typedef CHAR TCHAR,*PTCHAR,*PTSTR;
typedef CONST CHAR *PCTSTR;
#define _TEXT(quote) quote
#define _T(quote) quote
#endif
#define TEXT(quote) _TEXT(quote)
//下面这句话才是最重要的要记住的!!!
由此可以看出,“C”是指CONST,“T”表示如果使用UNICODE字符集的话就代表是“W”,即宽字符类型,PSTR是指向字符的指针类型,即char*
所以,如果使用UNICODE字符集的话,可以这样理解:
TCHAR ——> WCHAR
PCTSTR ——> PCWSTR ——> CONST PWSTR ——> CONST "wide" PSTR ——>const "wide" char* ——>const wchar_t*,同理,PTSTR可以理解成wchar_t*
所以平常用的时候要尽量使用TCHAR,PTSTR,PCTSTR
还有一个“L”,加一个“L”表明通知编译器应该把该字符串编译为一个UNICODE字符串,即字符串里的每个字符使用两个字节来表示,如LPSTR,LPCSTR指向的字符串里的字符都是占两个字节,但是L和T都出现的时候可以去掉其中一个,比如LPTSTR和LPCTSTR,去掉里面的L,就相当于PTSTR和PCTSTR,和原来没什么区别。
因为大家都习惯了C语言里的库函数,所以在Windows编程里会常常习惯性的用到,尤其是字符串处理函数,但是编译的时候又会发现错误,又或者编译通过而不能运行。其实原因也很简单,C语言的字符串函数支持的是ANSI字符集,所以我们在Windows编程里不能使用string.h里的字符串函数。建议使用的是头文件tchar.h里面的字符串处理函数,具体处理函数请看下一篇文章。
另外,Windows编程里在调用系统接口通常都有两种,如SetWindowText有SetWindowTextA和SetWindowTextW两种,一个支持ANSI字符集,一个支持UNICODE字符集。事实上,ANSI版本的函数的内部只分配内存,然后执行字符串转换,再调用该函数的UNICODE版本。不过平常我们只要用SetWindowText就行了,它的形式和上面的宏定义差不多,如果使用UNICODE字符集则内部用UNICODE版本的函数。
《Windows核心编程》这本书中对于Windows中的字符和字符串处理方式推荐:
1.将字符串当作字符数组看待
2.使用通用数据类型,如TCHAR,PTSTR等
3.避免使用prinf系列函数
4.使用安全的字符串处理函数
5.用tchar.h中的字符串处理函数
6.修改与字符串相关的计算,字符串所占的字符数和字节数不一定相同