>原著:Michael Dunn
>原文出处:<FONT size=2><a href="http://www.codeproject.com/string/cppstringguide1.asp" target="_blank" >CodeProject:The Complete Guide to C++ Strings, Part I</A></FONT></P>
>: p! C/ }/ C( \- v( R7 V( ]9 [
><B>引言</B>+ z" Y5 v4 F: _; Z/ T, z, n- ^
RE>wchar_t wch = L''1''; // 2 bytes, 0x0031( m& K& L/ j r* q
><IMG src="http://www.vckbase.com/document/image/paragraph.gif"> <B>字符在内存中是怎样存储的</B>% L, L' `, v$ L9 z( r
>Unicode的存储形式,L"Bob"</P>
>使用两个字节表示的0来做结束标志。
>值得注意的是,"ni"的值不能被解释成WORD型值0xfa93,而应该看作两个值93和fa以这种顺序被作为"ni"的编码。
> 因为x86CPU是little-endian,值0x0042在内存中的存储形式是42 00。你能看出如果这个字符串被传给strlen()函数会出现什么问题吗?它将先看到第一个字节42,然后是00,而00是字符串结束的标志,于是strlen()将会返回1。如果把"Bob"传给wcslen(),将会得出更坏的结果。wcslen()将会先看到0x6f42,然后是0x0062,然后一直读到你的缓冲区的末尾,直到发现00 00结束标志或者引起了GPF。
> 我们先来阐述规则2,因为找到一个违背它的真实的实例代码是很容易的。假设你有一个程序在你自己的目录里保存了一个设置文件,你把安装目录保存在注册表中。在运行时,你从注册表中读取安装目录,然后合成配置文件名,接着读取该文件。假设,你的安装目录是C:\Program Files\MyCoolApp,那么你合成的文件名应该是C:\Program Files\MyCoolApp\config.bin。当你进行测试时,你发现程序运行正常。
RE>bool GetConfigFileName ( char* pszName, size_t nBuffSize )# v9 I3 |$ f5 [3 D. H
> 当使用 GetConfigFileName() 检查尾部的''\\''时,它寻找安装目录名中最后的非0字节,看它是等于''\\''的,所以没有重新增加一个''\\''。结果是代码返回了错误的文件名。- X5 {1 h0 W9 K0 F8 n6 i
RE>bool FixedGetConfigFileName ( char* pszName, size_t nBuffSize )2 |9 _) _ d8 p' l0 G% s
RE>2a. 永远不要使用减法去得到一个字符串的索引。</PRE>3 Z! {! D" J# o9 H: M2 F
>违背这条规则的代码和违背规则2的代码很相似。例如,</P><
RE>char* pLastChar = &szConfigFilename [strlen(szConfigFilename) - 1];</PRE>' o7 g' t4 X, c0 V( D/ N
>这和向后移动一个指针是同样的效果。9 M' j) l( e7 e# \0 q$ p3 V
RE>BOOL WINAPI SetWindowTextA ( HWND hWnd, LPCSTR lpString );
RE>#define SetWindowText SetWindowTextA</PRE>& Q! C5 N* P4 W
> 这个宏定义把所有对SetWindowText的调用都转换成真正的API函数SetWindowTextA。(当然,你可以直接调用SetWindowTextA() 或者 SetWindowTextW(),虽然你不必那么做。)
RE>HWND hwnd = GetSomeWindowHandle();
>在预处理器把SetWindowText用SetWindowTextW来替换后,代码变成:</P><
RE>HWND hwnd = GetSomeWindowHandle();' `; C$ F$ w0 q. X6 t5 i5 |6 C
> 看到问题了吗?我们把单字节字符串传给了一个以Unicode字符串做参数的函数。解决这个问题的第一个方案是使用 #ifdef 来包含字符串变量的定义:</P><
RE>HWND hwnd = GetSomeWindowHandle();3 B$ S* F H! y4 n0 R
>你可能已经感受到了这样做将会使你多么的头疼。完美的解决方案是使用TCHAR.
RE>#ifdef UNICODE
>所以用MBCS来build时,TCHAR是char,使用UNICODE时,TCHAR是wchar_t。还有一个宏来处理定义Unicode字符串常量时所需的L前缀。</P><
RE>#ifdef UNICODE| 欢迎光临 数学建模社区-数学中国 (http://www.madio.net/) | Powered by Discuz! X2.5 |