VC中一个关于宏的使用问题.doc_第1页
VC中一个关于宏的使用问题.doc_第2页
VC中一个关于宏的使用问题.doc_第3页
VC中一个关于宏的使用问题.doc_第4页
免费预览已结束,剩余1页可下载查看

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

一课资料网/VC 中一个关于宏的使用问题这儿是个关于宏的问题, 我曾用过 ATL 的串转换宏, 包括 W2A , 开 始有些东西我还不太明白。为了使用这些宏,必须在函数的开始处用 USES_CONVERSION来初始化某些局部变量。用就用吧,但是看看这 个宏的定义,它有类似下面的代码:1./ 在 atlconv.h 文件中2.#define USES_CONVERSION 3.int _convert; _convert; 4.UINT _acp = GetACP(; _acp; 5.LPCWSTR _lpw; _lpw; 6.LPCSTR _lpa; _lpa为什么它们用“ int x;x;”这种后面跟着变量的声明?很多人都碰到过这个令人困惑的问题,后来发现简单的答案是:禁 止编译器的警告信息(warning 。如果单独有一行代码:1.int x;且从来没有使用过 x ,那么编译器汇报错“ unreferenced local variable :x ” , 意思是未引用过的局部变量 x ,如果将警告信息的输出调 到最大。为了避免讨厌的警告, USES_CONVERSION引用声明的变量。1.int x; / 声明2.x; / 使用这个变量在 C+之前的时代,程序员有时在 C 中用函数形参做同样的事情来 避免“ unreferenced formal parameter”或其它的深奥费解的编译错 误。1.void MyFunc(intx, chary2.3.x;4.y;5.6.当然,现在用下面的代码可以更有效地完成同样的事情:1./ 参数 x 不是用2.void MyFunc(int/* x */3.4.5.也就是说声明参数,但不给它起名,不能这样使用局部变量;必须 显式地引用它。这样做不会增加任何指令到代码中。最多可能多增加几 个字节到堆栈(为 x 预留空间。灵巧的编译器甚至不会操心 x 从来没 有被使用过虽然好奇心可能想知道:如果编译器够厉害,知道了从 没有使用 x ,为什么要抱怨(编译出错呢?答案是因为苛刻的程序员 (且编程能力与个人的记性有关使用编译警告提醒自己删除某部分代 码时发生变量荒废。这种警告在 C 时代很有用,你必须在每个函数的顶 部声明变量,这就远离了实用它们的代码。现在来看看另一个问题:为什么在开始位置要用USES_CONVERSION?即为什么 W2A&Co之类的宏还需要另外的宏 声明自己的变量;为什么不直接在 W2A 中声明这个变量?1.#define W2A(x 2.int _convert; _convert; 3.etc很明显这样做不行, 因为如果你使用 W2A 两次, 得到一个复制的变 量。那为什么不把整个宏放进花括弧创建新的范围?1.#define W2A(x Q 2.int _convert; _convert; 3. 4.这样解决了命名冲突,但不能进行如下编码: 1.DoSomething(W2A(pwstr;没有办法从代码块返回值,所以不能在函数调用中传递 W2A 。真笨 啊,那么内联函数怎么样?1.inline LPCSTR W2A(LPWSTRw 2.int_convert;3.4.这解决了范围问题任何 W2A 需要的变量多可以在这个函数中, 在自己的范围内声明, 不需要另外的宏。 它也提供了一种返回值的方式, 使你可以在函数调用和赋值中使用 W2A (x 。但是这种方法不灵,也 是因为 W2A 的缘故和其它的宏更复杂。不管什么时候进行 Unicode 转换,都不能就地转换串,必须分配一 个临时串容纳被转换的字节。典型地,通过调用 new 分配一个串:1.int len = MultiByteToWideChar(.,2.mystr, NULL, 0; / 或的长度3.LPWSTR p = newWCHARnLen; / 分配内存4.MultiByteToWideChar(.,p,len; / 转换5.SomeCOMFunction(p; / 使用之6.delete p; / 销毁这段代码不仅令人讨厌,而且还没有效率;必须调用 MultiByteToWideChar 两次(一次是计算长度,一次是实际的转换, 你得从堆中分配 p , 这样很慢。 通过分配 2*len个字节解决第一个问题, 这里长度 len 是 ASCII 串的长度但第二个问题怎么办?如果看看 A2W 是如何展开的,请看:1./ 简化版2.#define A2W(s 3._len = 2*strlen(s;4.AfxA2WHelper(LPWSTRalloca(_len;AfxA2Whelper 是一个调用 MultiByteToWideChar 的辅助函数。 A2W 使用 2*len巧妙地避免了两次调用 MultiByteToWideChar 。但 A2W 及其它转换宏真正聪明的地方是不调用 new 操作分配临时串,而 是调用 alloca 在栈中分配字节,而不是在堆中。这样做非常快,因 为编译器要做的只是增加栈指针。不调用函数,不处理内存块。它也避 免了内存碎片,并且也没有必要调用 delete 操作,因为当控制离开 alloca 被调用的地址后,内存被自动释放。这正好说明了为什么 A2W 不能时内联函数; 如果是的话, alloca 创建的临时串会在返回前被摧毁, 并且你会以删除串的方式终止 SomeCOMFunction (使用这个例子 调 用。A2W 必须从 alloca 被调用的相同的地址处调用 alloca 所以 A2W 必须是一个宏,不是一个函数;因此它需要另一个宏USERS_CONVERSION来声明 _len以及其它一些用到的变量(为了简化, 我省略了 。 当你仔细想想, 整个处理告诉我们要想写一组类似 A2W 的宏从栈中的分配内存会减少很多不必要的麻烦。另外,任何时候,只 要你想要快速地获取临时内存,都可以调用 alloca 。下面的代码是我们 常常见到的:1.char* p = newcharlen;2.DoSomething(p;3.delete p;使用下面的代码替代之会效率更高:1.char *p = (char*alloca(len;2.DoSomething(p;3./ 不用调用 d

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论