分类: C/C++
2008-05-31 09:03:06
CString s(\"GrayCat\");
LPCTSTR p = s;
它可以正确地运行。这是由C语言的强制类型转化规则实现的。当需要强制类型转化时,C++规测容许这种选择。比如,你可以将(浮点数)定义为将某个复数 (有一对浮点数)进行强制类型转换后只返回该复数的第一个浮点数(也就是其实部)。可以象下面这样:
Complex c(1.2f, 4.8f);
float realpart = c;
如果(float)操作符定义正确的话,那么实部的的值应该是1.2。
这种强制转化适合所有这种情况,例如,任何带有 LPCTSTR 类型参数的函数都会强制执行这种转换, 于是,你可能有这样一个函数(也许在某个你买来的DLL中):
BOOL DoSomethingCool(LPCTSTR s);
你象下面这样调用它:
CString file(\"c:\\\\myfiles\\\\coolstuff\")
BOOL result = DoSomethingCool(file);
它能正确运行。因为 DoSomethingCool 函数已经说明了需要一个 LPCTSTR 类型的参数,因此 LPCTSTR 被应用于该参数,在 MFC 中就是返回的串地址。
如果你要格式化字符串怎么办呢?
CString graycat(\"GrayCat\");
CString s;
s.Format(\"Mew! I love %s\", graycat);
注意由于在可变参数列表中的值(在函数说明中是以“...”表示的)并没有隐含一个强制类型转换操作符。你会得到什么结果呢?
一个令人惊讶的结果,我们得到的实际结果串是:
\"Mew! I love GrayCat\"。
因为 MFC 的设计者们在设计 CString 数据类型时非常小心, CString 类型表达式求值后指向了字符串,所以这里看不到任何象 Format 或 sprintf 中的强制类型转换,你仍然可以得到正确的行为。描述 CString 的附加数据实际上在 CString 名义地址之后。
有一件事情你是不能做的,那就是修改字符串。比如,你可能会尝试用“,”代替“.”(不要做这样的,如果你在乎国际化问题,你应该使用十进制转换的 National Language Support 特性,),下面是个简单的例子:
CString v(\"1.00\"); // 货币金额,两位小数
LPCTSTR p = v;
p[lstrlen(p) - 3] = \'\',\'\';
这时编译器会报错,因为你赋值了一个常量串。如果你做如下尝试,编译器也会错:
strcat(p, \"each\");
因为 strcat 的第一个参数应该是 LPTSTR 类型的数据,而你却给了一个 LPCTSTR。
不要试图钻这个错误消息的牛角尖,这只会使你自己陷入麻烦![Page]
原因是缓冲有一个计数,它是不可存取的(它位于 CString 地址之下的一个隐藏区域),如果你改变这个串,缓冲中的字符计数不会反映所做的修改。此外,如果字符串长度恰好是该字符串物理限制的长度(梢后还会讲到这个问题),那么扩展该字符串将改写缓冲以外的任何数据,那是你无权进行写操作的内存(不对吗?),你会毁换坏不属于你的内存。这是应用程序真正的死亡处方。