ATL and MFC String Conversion Macros
此处讨论的字符串转换宏对 ATL 和 MFC 都有效。 有关 MFC 字符串转换的详细信息,请参阅 TN059:使用 MFC MBCS/Unicode 转换宏和 MFC 宏和全局。
ATL 7.0 字符串转换类和宏
ATL 3.0 字符串转换宏
ATL 7.0 字符串转换类和宏
ATL 7.0 引入了多个新转换类和宏,相对于现有宏已有很大的改进。
新字符串转换类和宏的名称采用以下形式:
CSourceType2[C]DestinationType[EX]
其中:
下表中介绍了 SourceType 和 DestinationType。
[C] 在目标类型必须是常量时存在。
[EX] 在缓冲区初始大小必须指定为模板参数时存在。
SourceType/DestinationType
描述
A
ANSI 字符串。
W
Unicode 字符串。
T
通用字符串(定义 _UNICODE 时与 W 等效,否则与 A 等效)。
OLE
OLE 字符串(与 W 等效)。
例如,若要从 Unicode 字符串转换为通用字符串,而无需更改转换的字符串,请使用 CW2CT。
警告
不支持上面列出的模式的某些排列。不支持 CA2CW 和 CW2CA(以及 CA2CWEX 和 CW2CAEX)。对于 OLE 字符串转换,仅支持 COLE2T 和 CT2OLE (以及 COLE2CT、COLE2TEX、COLE2CTEX、CT2COLE、CT2OLEEX 和 CT2COLEEX)。有关详细信息,请参阅 atlconv.h。
如果已知已转换字符串不太可能多于 64 个字符,则 EX 版本(例如 CW2CTEX<64>)可用于节省堆栈上的空间。
备注
与 BSTR 字符串之间来回转换的推荐方式是使用 CComBSTR 类。若要转换为 BSTR,请将现有字符串传递给 CComBSTR 的构造函数。若要从 BSTR 转换,请使用 COLE2[C]DestinationType[EX],(例如 COLE2T)。
需要缓冲区的新转换类(CA2AEX、CA2WEX、CW2AEX 和 CW2WEX)使用固定大小的静态缓冲区以存储转换的结果。 如果结果过大,无法放入静态缓冲区,则该类将使用 malloc 分配内存,并在对象超出范围时释放内存。 和早期的文本转换宏不同,这保证了这些类可以在循环中安全使用,并且不会使堆栈溢出。
ATL 7.0 中已引入的转换宏适用于识别输入的 NULL 字符串。 如果在未分配任何内存的情况下输入参数是 NULL,则这些宏将返回 NULL。
默认情况下,ATL 转换类和宏将使用用于转换的当前线程的 ANSI 代码页。 如果要使用基于类 CA2WEX 或 CW2AEX 的宏重写特定转换的该行为,请将代码页指定为该类的构造函数的第二个参数。
![]() |
---|
在将字符串传递到这些宏之前检查这些字符串的长度以避免潜在的缓冲区溢出问题。堆栈溢出是也可以用 try/except 捕获的异常。 |
早期字符串转换宏和新字符串转换类之间有多个重要的区别:
早期 ATL 3.0 转换宏 |
新的 ATL 7.0 转换类 |
---|---|
在堆栈上分配内存。 |
将堆栈内存用于小字符串。 如果堆栈不够大,则使用堆。 |
当退出函数时,将释放该字符串。 |
当变量超出范围时,将释放该字符串。 |
不可用于异常处理程序。 |
可用于异常处理程序。 |
不适合在循环中使用。 内存使用量增长,直到退出该函数。 |
支持在循环中使用。 循环范围可确保在每次迭代时释放内存。 |
不适用于大字符串。 堆栈空间有限。 |
可以用于大字符串。 字符串将在堆上分配。 |
通常需要定义 USES_CONVERSION。 |
从不需要定义 USES_CONVERSION。 |
OLE 的意义取决于 OLE2ANSI 的定义。 |
OLE 始终与 W 等效。 |
示例
代码
//Example 1
// Convert LPCWSTR to LPCSTR.
void ExampleFunction1(LPCWSTR pszW)
{
// Create an instance of CW2A, called pszA,
// and initialize it with pszW.
CW2A pszA(pszW);
// pszA works like an LPCSTR, and can be used thus:
ExampleFunctionA(pszA);
// Note: pszA will become invalid when it goes out of scope.
}
// Example 2
// Use a temporary instance of CW2A.
void ExampleFunction2(LPCWSTR pszW)
{
// Create a temporary instance of CW2A,
// and initialize it with pszW.
ExampleFunctionA(CW2A(pszW));
// Note: the temporary instance becomes invalid
// after the execution of the statement above.
}
// Example 3
// Incorrect use of conversion macros.
void ExampleFunction3(LPCWSTR pszW)
{
// Create a temporary instance of CW2A,
// save a pointer to it and then delete
// the temportary instance.
LPCSTR pszA = CW2A(pszW);
// The pszA in the following line is an invalid pointer,
// as the instance of CW2A has gone out of scope.
ExampleFunctionA(pszA);
}
有关临时类实例的警告
应强调,以下不是良好的代码:
LPCTSTR szr = CA2T(szReplaceFile);
使用 ATL 3.0 宏时,可接受使用:
LPCTSTR szr = A2T(szReplaceFile);
因为由转换函数分配的内存在退出当前函数之前不会释放。 相同的代码不适用于新类。
此代码:
LPCTSTR szr = CA2T(szReplaceFile);
等效于此:
LPCTSTR szr;
{
CA2T temp(szReplaceFile);
szr = temp.operator LPTSTR();
}
由于在销毁临时对象时销毁了由临时对象分配的和从强制转换运算符返回的内存,因此使用 szr 中的值将导致意外结果。
改用此代码:
CA2T szr(szReplaceFile);
强制转换运算符使 CA2T 对象外观像 LPCTSTR。
高级用法
默认静态缓冲区大小为 128 个字符。 如果缓冲区大小必须针对特定转换更改,请使用 EX 版本的宏,并将缓冲区大小指定为模板参数。
// Example 4
// Changing the size of the buffer.
void ExampleFunction4(LPCWSTR pszW)
{
// Use a 16-character buffer.
ExampleFunctionA(CW2AEX<16>(pszW));
}
以下是将代码页指定为该类的构造函数的第二个参数的示例。
// Example 5
// Specifying the code page.
void ExampleFunction5(LPCWSTR pszW)
{
// Convert to the Macintosh code page
ExampleFunctionA(CW2A(pszW, CP_MACCP));
}
ATL 3.0 字符串转换宏
仍然提供原始文本转换宏,并且在下表中列出:
ATL 3.0 字符串转换宏
A2BSTR |
OLE2A |
T2A |
W2A |
A2COLE |
OLE2BSTR |
T2BSTR |
W2BSTR |
A2CT |
OLE2CA |
T2CA(已弃用。 改用 T2CA_EX 或 CT2CA。) |
W2CA |
A2CW |
OLE2CT |
T2COLE |
W2COLE |
A2OLE |
OLE2CW |
T2CW |
W2CT |
A2T |
OLE2T |
T2OLE |
W2OLE |
A2W |
OLE2W |
T2W |
W2T |
使用这些宏的语法如下所示:
MACRONAME( string_address )
例如:
A2W(lpa);
在宏名称中,源字符串类型在左边(例如,A),而目标字符串类型在右边(例如,W)。 A 代表 LPSTR,OLE 代表 LPOLESTR,T 代表 LPTSTR,W 代表 LPWSTR。
如果宏名称中有 C,则该宏转换为 const 字符串。 例如,W2CA 将 LPWSTR 转换为 LPCSTR。
因此,A2W 将 LPSTR 转换为 LPWSTR,OLE2T 将 LPOLESTR 转换为 LPTSTR 等。
ATL 字符串转换宏的行为取决于有效的编译器指令(如果有)。 如果源和目标类型相同,则不发生转换。 编译器指令更改 T 和 OLE,如下所示:
有效的编译器指令 |
T 变为 |
OLE 变为 |
---|---|---|
无 |
A |
W |
_UNICODE |
W |
W |
OLE2ANSI |
A |
A |
_UNICODE 和OLE2ANSI |
W |
A |
使用 _alloca 创建目标字符串,除非目标类型是 BSTR。 使用 _alloca 将从堆栈分配内存,以便在函数返回时将自动对其进行清理。 默认情况下,此宏一次最多转换 500KB。
使用 ATL 字符串转换宏时,请在函数的开头指定 USES_CONVERSION 宏以避免编译器错误。 例如:
void StringFunc(LPSTR lpsz)
{
USES_CONVERSION;
LPWSTR x = A2W(lpsz);
// Do something with x
wprintf_s(L"x is %s", x);
}
要求
头文件:AtlBase.h、AtlConv.h(在 AtlConv.h 中声明)
请参见
参考
DEVMODE and TEXTMETRIC String Conversion Macros