1、缓冲区溢出错误是处理字符串时的典型错误。
2、一般情况下Unicode都是指UTF-16,即每个字符编码为两个字节。大部分的WindowsAPI都是直接对Unicode字符串进行操作,所传入的多字节字符串会先转换为Unicode后再拿来使用。
3、C语言用char数据类型来表示一个8位ANSI字符。在VC中定义了一个内置的数据类型wchar_t,它表示一个16位的Unicode字符。
定义语句是:typedef unsigned short wchar_t;
定义举例:wchar_t a= L'a';
wchar_t array[100] = L"Hello world!";
对于array数组,它的每个字符都占16位且是以16位的\0结尾。
4、字符和字符串前的L是一个宏。它通知编译器应该将其编译为Unicode字符串。当编译器将此字符串放入程序的数据段时,会使用UTF-16来编码每个字符。
WinNT.h头文件还定义了一系列的数据类型来处理字符指针和字符串指针。
5、#define UNICODE
typedef WCHAR TCHAR,*PTCHAR , PTSTR;
typedef COSNT WCHAR *PCTSTR;
#define _TEXT(quote) L##quote
#else
typedef CHAR TCHAR ,*PTCHAR,PTSTR;
typedef CONST CHAR *PCTSTR;
#define _TEXT(quote) quote
#endif
#define TEXT(quote) _TEXT(quote)
编译器使用预编译宏来进行判断,如果定义了UNICODE,就会将WCHAR定义为TCHAR,在_TEXT,在TEXT的参数前加上L。否则将TCHAR定义为CHAR,TEXT,_TEXT的参数前没有添加任何东西。如:
TCHAR c=TEXT('a');
TCHAR array[100]=TEXT("Hello world!");
编译器会根据我们的设置,编译成不同的代码。
6、在Unicode环境下,由于定义了UNICODE上述宏经过展开后会生成以下代码:
WCHAR c=L'a';
WCHAR array=L"Hello world!";
而在ANSI字符集下会生成这样的代码:
CHAR c='a';
CHAR array="Hello world!";
7、如果一个windows函数参数列表中存在字符串,它通常有两个版本。一个接受Unicode字符串另一个接受ANSI字符串。用Visual Studio创建一个新项目的时候,它默认会定义UNICODE。
8、导出dll时,可以考虑导出两个函数一个ASNI版本,一个Unicode版本。ANSI版本仅执行字符串转换操作之后调用Unicode版本的函数。
9、C运行库也提供了不同的函数处理不同的字符集,但是与windows不同的是c运行库的ANSI版本的函数不会在内部调用Unicode版本的函数。
C语言提供的对字符串进行修改的函数存在安全隐患,容易造成缓冲区溢出。轻则结果错误,重则系统崩溃。因为它们对目标缓冲区进行操作时没有收到指定缓冲区的最大长度的参数,函数并不知道自己会破坏内存。
10、如strlen用于处理ANSI字符集,返回字符串长度,与之对应的Unicode版本为wcslen。(wide character set)。
所有要使用安全的函数程序必须包含StrSafe.h头文件。现有的每一个函数,如strcpy,_tcscpy都有一个对应的安全新版本函数,strcpy_s,_tcscpy_s。前面的名称相同但最后添加了一个_s,代表更安全。
如老版本的函数的区别是它们需要目标缓冲区的大小。注意不是字符串所占的字节数,而是字符数,无论是ANSI字符还是Unicode字符集都可以使用宏_countof来得到字符数(使用sizeof不行,因为它返回字节数)。如果目标缓冲区不足以容纳结果数据,函数就会设置局部于线程的C运行时变量errno。然后返回一个errno_t值来指出成功或失败。
11、要表示字节可以使用BYTE。建议平时使用通用的数据类型如TCHAR,PTSTR定义变量。同时将字符或字符串用TEXT或_T包括起来。
12、int CompareString( )函数用来对两个字符串进行比较。
int MultiByteToWideChar( )将多字节字符串转换为宽字符字符串。
int WideCharToMultiByte( )将宽字符字符串转换为多字节字符串。
BOOL IsTextUnicode( )判断字符串是Unicode还是ANSI字符集。