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

警告

不支持上面列出的模式的某些排列。不支持 CA2CWCW2CA(以及 CA2CWEXCW2CAEX)。对于 OLE 字符串转换,仅支持 COLE2TCT2OLE (以及 COLE2CTCOLE2TEXCOLE2CTEXCT2COLECT2OLEEXCT2COLEEX)。有关详细信息,请参阅 atlconv.h。

如果已知已转换字符串不太可能多于 64 个字符,则 EX 版本(例如 CW2CTEX<64>)可用于节省堆栈上的空间。

备注

与 BSTR 字符串之间来回转换的推荐方式是使用 CComBSTR 类。若要转换为 BSTR,请将现有字符串传递给 CComBSTR 的构造函数。若要从 BSTR 转换,请使用 COLE2[C]DestinationType[EX],(例如 COLE2T)。

需要缓冲区的新转换类(CA2AEXCA2WEXCW2AEXCW2WEX)使用固定大小的静态缓冲区以存储转换的结果。 如果结果过大,无法放入静态缓冲区,则该类将使用 malloc 分配内存,并在对象超出范围时释放内存。 和早期的文本转换宏不同,这保证了这些类可以在循环中安全使用,并且不会使堆栈溢出。

ATL 7.0 中已引入的转换宏适用于识别输入的 NULL 字符串。 如果在未分配任何内存的情况下输入参数是 NULL,则这些宏将返回 NULL。

默认情况下,ATL 转换类和宏将使用用于转换的当前线程的 ANSI 代码页。 如果要使用基于类 CA2WEXCW2AEX 的宏重写特定转换的该行为,请将代码页指定为该类的构造函数的第二个参数。

安全说明安全说明

在将字符串传递到这些宏之前检查这些字符串的长度以避免潜在的缓冲区溢出问题。堆栈溢出是也可以用 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_EXCT2CA。)

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 代表 LPSTROLE 代表 LPOLESTRT 代表 LPTSTRW 代表 LPWSTR

如果宏名称中有 C,则该宏转换为 const 字符串。 例如,W2CALPWSTR 转换为 LPCSTR

因此,A2WLPSTR 转换为 LPWSTROLE2TLPOLESTR 转换为 LPTSTR 等。

ATL 字符串转换宏的行为取决于有效的编译器指令(如果有)。 如果源和目标类型相同,则不发生转换。 编译器指令更改 TOLE,如下所示:

有效的编译器指令

T 变为

OLE 变为

A

W

_UNICODE

W

W

OLE2ANSI

A

A

_UNICODEOLE2ANSI

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

其他资源

ATL 宏