ATL 7.0介绍了一些新的转换类和宏,为现有的宏提供了重要的改进。
新的字符串转换类和名称宏的形式是:C 源类型 2[C] 目标类型[EX]
其中:
•源类型和目标类型描述如下表.
• [C]是目标类型必须是只读的.
•[EX]是缓冲器的初始大小必须被指定为一个模板参数。

源类型/目标类型  描述
ANSI字符串
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.
注意:

对于BSTR字符串的转换操作推荐使用CComBSTR类,转换为BSTR时将现有的字符串传入CComBSTR的构造函数,从BSTR转换,使用COLE2[C] 目标类型[EX],比如COLE2T。
新的转换类要求用一个固定大小的静态缓存区来存储转换结果。如果结果太大而不适合静态缓存区,类将使用malloc来分配内存,并在对象超出范围之后释放内存。不像较早的文本转换宏,以上特性保证了这些类在循环中的安全使用,避免了栈溢出。
默认情况下,ATL转换类和转换宏使用当前线程的ANSI代码页转换。如果有特殊转换需要覆盖默认行为,可以使用基于类CA2WEX 或 CW2AEX的宏,在类的构造函数的第二个参数指定代码页。

安全提醒:
将字符串传入这些宏之前检查长度可以避免潜在的缓冲区溢出问题。堆栈溢出可以通过try/except抓取。

旧的字符串转换宏和新的字符串转换类之间的几个重要区别:

Old ATL 3.0 Conversion Macros New ATL 7.0 Conversion Classes
在栈上分配内存 小字符串在栈上,栈内存不足则使用堆
函数退出时释放字符串 变量超出范围时释放字符串
无异常处理  可以在异常处理中使用
不适合循环使用,内存增长直到函数退出  支持循环使用 循环范围确保内存被释放在每个迭代
不适合大的字符串,栈内存有限  支持大字符串,堆上分配内存
需要USES_CONVERSION  不再需要USES_CONVERSION
OLE的意义取决于OLE2ANSI的定义 . OLE始终等于W
示例代码:
//Example 1
// 将LPCWSTR 转为 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
// 使用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
// 转换宏的错误使用
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); //ERROR USE
// 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);

使用ATL3.0宏,这是可以接受的使用方法:
LPCTSTR szr = A2T(szReplaceFile);   //A2T→ ATL 3.0
因为由转换函数申请的内存直到函数退出时才释放。同样的代码在新的(ATL 7.0)类中是不工作的。

为什么呢?
这行代码
 LPCTSTR szr = CA2T(szReplaceFile); 
实际上等价于
LPCTSTR szr;
{
   CA2T temp(szReplaceFile);
   szr = temp.operator LPTSTR();
}   
因为内存是由临时对象申请的、由类型转换操作符返回的,当对象销毁时它也销毁了,再使用szr的值结果将是未知的。替换代码是,
CA2T szr(szReplaceFile);   
这样,类型转换操作符(cast operator)生产了一个LPCTSTR.

高阶使用
默认的静态缓冲区大小是128个字符,如果需要改变缓冲区的大小,使用EX版本的宏,并以模板参数指定缓冲区的大小。

// Example 4
// 改变缓冲区的大小
void ExampleFunction4(LPCWSTR pszW)
{
// 使用16个字符的缓冲区.
ExampleFunctionA(CW2AEX<>(pszW));
} 下面是一个通过类构造函数的第二个参数指定代码页大小的例子:
// Example 5
// 指定代码页.
void ExampleFunction5(LPCWSTR pszW)
{
// Convert to the Macintosh code page
ExampleFunctionA(CW2A(pszW, CP_MACCP));
}

ATL 3.0 字符串转换宏

原始文本转换宏仍然可用,列于下表:
ATL3.0字符串转换宏:
A2BSTR OLE2A  T2A  W2A 
A2COLE  OLE2BSTR  T2BSTR  W2BSTR 
A2CT  OLE2CA  T2CA W2CA 
A2CW  OLE2CT  T2COLE  W2COLE 
A2OLE  OLE2CW  T2CW  W2CT 
A2T  OLE2T  T2OLE  W2OLE 
A2W  OLE2W  T2W  W2T

其中T2CA (不推荐. 用 T2CA_EX 或 CT2CA 替换)
使用这些宏的语法:MACRO_NAME( string_address ) e.g.: A2W(lpa);
在宏名中,源字符串类型在左,目标字符串类型在右。
A表示LPSTR,OLE代表LPOLESTR,T代表LPTSTR,而W代表LPWSTR。
如果宏名中有‘C’,则表示转为const字符串。例如,W2CA将LPWSTR 转为 LPCSTR.
A2W 将LPSTR 转为 LPWSTR, OLE2T 将 LPOLESTR 转为 LPTSTR,等等.
ATL字符串转换宏的行为依赖于实际的编译指令,如果有的话。如果源类型和目的类型相同,则不作任何转换。

编译器指令对T和OLE的改变如下:

编译器指令 T变成 OLE变成
NONE  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 (declared in AtlConv.h)
参见
参考DEVMODE and TEXTMETRIC String Conversion Macros 
其它资源ATL Macros

原文

ATL and MFC String Conversion Macros的更多相关文章

  1. ATL、MFC、WTL CString 的今生前世(转载)

    转载:https://www.cnblogs.com/tekkaman/archive/2011/04/20/2022650.html 上文分析了ATL.MFC CString的设计和实现,我们不禁会 ...

  2. Specify a culture in string conversion explicitly

    Specify a culture in string conversion explicitly There are different methods of grouping symbols, l ...

  3. 用ATL和MFC来创建ActiveX控件

    摘要:目前MFC和ATL代表了两种框架,分别面向不同类型的基于Windows的开发.MFC代表了创建独立的Windows应用的一种简单.一致的方法:ATL提供了一种框架来实现创建COM客户机和服务器所 ...

  4. curl Array to string conversion 错误

    0x00 故障 由于GuzzleHttp在iis上使用错误,于是开始替换其为Unirest,没想到发送了一个curl Array to string conversion 错误 0x01 原因 跟踪调 ...

  5. Notice:Array to string conversion的问题

    如果后台或者前端输出这样的提示: Notice: Array to string conversion 原因是:用 echo  来输出数组,当然会报错,数组应该用print , print_r , 或 ...

  6. php报错Array to string conversion 解决方案,动态输出数据库列名称

    php报错Array to string conversion 解决方案,动态输出数据库列名称 问题:在Windows php5.3环境下使用:<?php echo $row->$keys ...

  7. 解决warning: #181-D: argument is incompatible with corresponding format string conversion警告

    uint8_t NetRSSI=0;uint8_t NetBer=0;uint8_t failtime=0; sscanf(&USART_RX_BUF[0],"%*s%u,%u&qu ...

  8. php YII2空数组插入报错问题处理 Array to string conversion

    问题描述 前端传空数组 [],php接收后处理不当插入数据库时报错Array to string conversion 参数示例 { "id": 0, //ID整型 "t ...

  9. VS2008中 ATL CLR MFC Win32 区别

    ATL用于编写COM程序,CLR是.NET的公共语言运行库,MFC是指MFC类库,MFC程序是用这些类库做出的程序,WIN32常规就是不用MFC,使用API函数编的程序.MFC.ATL和CLR是VC2 ...

随机推荐

  1. python编写简单的html登陆页面(1)

    1  html 打开调式效果如下 2  用python后台编写 # coding:utf-8# 从同一个位置导入多个工具,# 这些工具之间可以用逗号隔开,同时导入# render_template渲染 ...

  2. Co-prime HDU - 4135_容斥计数

    Code: #include<cstdio> #include<cstring> #include<cmath> #include<iostream> ...

  3. Day 08 字符编码

    字符编码 计算机基础 启动应用程序 1.双击QQ 2.操作系统接受指定然后把该操作转化为0和1发送给CPU 3.CPU接受指令然后把指令发给内存 4.内存接受指令把指令发送给硬盘获取数据 5.QQ在内 ...

  4. python3发送邮件

    import smtplib from email.mime.text import MIMEText from email.utils import formataddr import psutil ...

  5. Project Euler 27 Quadratic primes( 米勒测试 + 推导性质 )

    题意: 欧拉发现了这个著名的二次多项式: f(n) = n2 + n + 41 对于连续的整数n从0到39,这个二次多项式生成了40个素数.然而,当n = 40时402 + 40 + 41 = 40( ...

  6. 计蒜客 阿里天池的新任务—简单( KMP水 )

    链接:传送门 思路:KMP模板题,直接生成 S 串,然后匹配一下 P 串在 S 串出现的次数,注意处理嵌套的情况即可,嵌套的情况即 S = "aaaaaa" ,P = " ...

  7. C语言求大数的阶乘

    我们都知道如何计算一个数的阶乘,可是,如果这个数很大呢,该如何计算? 当一个数很大时,利用平常的方法是求不出来它的阶乘的,因为数据超出了范围.因此我们要用数组来求一个大数的阶乘,用数组的每位表示结果的 ...

  8. P3378 【模板】堆

    题目描述 如题,初始小根堆为空,我们需要支持以下3种操作: 操作1: 1 x 表示将x插入到堆中 操作2: 2 输出该小根堆内的最小数 操作3: 3 删除该小根堆内的最小数 输入输出格式 输入格式: ...

  9. PuTTY_0.67.0.0工具链接linux

    1.虚拟机设置 在网络适配器中选中桥接模式,勾选复制物理网络链接状态(p)选项.点击确认. 2.开启虚拟机,检查是否安装有ssh服务器 a.查看是否启动ssh服务器 ps -a | grep ssh ...

  10. 汇编-理解call,ret

    ; 有意思的东西,主函数调用子函数用汇编来理解 assume cs:codeseg codeseg segment start: main: call sub1 ; 调用子函数1, push IP1 ...