分类: C/C++
2008-03-17 11:18:48
许多 C++ 爱好者已经对我最近的专栏中渗入了太多关于C#的内容表示关注。我承认这一点!我唯一的辩解是:由于 Microsoft® .NET Framework 已经获得广泛的认同,给我发送关于C#问题的读者越来越多,同时因为C# 和 C++ 如此类似,所以我就回答了一部分他们的问题。这不是我有意疏远 C++ 爱好者——上帝知道,我就是他们中的一员啊!不管怎样,为了突出重点,从这个月开始的 C++ 专栏将更多地专注于 C++ 的内容,包括托管扩展以及 MFC 这样的传统内容。因此提出你的 C++ 问题吧!我特别鼓励你提出关于托管 C++ 的问题。你使用它的时候有些什么体会? Jeff Partch
#if (WINVER >= 0x0400) #define WM_APP 0x8000 #endif 正如每个 Windows 极客(Geek)所知道的那样,WINVER 0x0400 是指 Windows 95、Windows 98 和 Windows NT。所以 WM_APP 的使用还不到十年,这解释了为什么我没注意到它——在 2005 年之前,我不应该对下一个十年的消息范围妄加评论! UINT WM_SAYHELLO = RegisterWindowMessage(_T("WmSayHello")); 这时其它协作应用程序可以用这个特定的名称“WmSayHello”注册并获得相同的值,于是他们都可以互相通信。每个 Windows 会话实际的 WM_SAYHELLO 值 将会各不相同,但在某一个对话中,注册它的所有应用程序将具有相同的值。当然,该值将总在 0xC000 - 0xFFFF 范围之内。糟了——MSDN® 杂志有最精明的读者! Randy Goodwin
// String* c2 = new String(_T("This is a TCHAR string")); ldsflda valuetype $ArrayType$0x11197cc2 modopt([Microsoft.VisualC]Microsoft.VisualC.IsConstModifier) ''?A0x1f1e2151.unnamed-global-0'' newobj instance void [mscorlib]System.String::.ctor(int8*)我会马上解释这段冗长而令人费解的文字,但其基本思路是编译器加载了 C++ 字符串文字量的地址,然后产生一个 newobj 指令,该指令将文字量地址到 String 的构造函数。另外,编译器为非托管字符串文字量创建了一个专门的 Array 类型——这就是前面代码段中样子奇怪的 $ArrayType$0x11197cc2,还有一个 被命名为?A0x1f1e2151.unnamed-global-0 的静态实例,如图 Figure 3 所示:
如果你花点时间看看 MSIL,你将发现 modopts 无处不在。一个 modopt 的完全描述已超出了本栏目范围,但是其基本思路是编译器 能用 modopt 提供有关公共语言运行时无法理解的类型的附加信息,但是该程序集的其它使用者可能理解——在这种情况下,该信息就是全局常量。CLR本身没有常量的概念,但是 程序集的其它使用者可能知道。如果该程序集被引入 C++,则 C++ 编译器会知道该变量是个常量;但是如果该程序集被 C# 使用,C# 编译器将会忽略 modopt 常量,因为 C# 没有常量的概念,正如你所能看到的,当你在托管代码中使用原生类型时有许多奇怪或迷惑发生。 // String* s1 = new String(S"This is a String literal"); ldstr "This is a String literal" 这里没有函数调用,仅有一个 ldstr 指令。这个指令将引用某个字符串文字量的新对象压入,储存在程序的元数据中。无论是用文字量创建 String 对象还是直接将它传递给需要字符串的 某些函数,都是如此: // Console::WriteLine(S"World"); ldstr "World" call void [mscorlib]System.Console::WriteLine(string) 了解所发生的事情的另外一种方法是用/FAs编译程序来生成一个程序集列表。(是的,它也可以用于 MSIL)Figure 5 展示了用/FAs编译 StrLit 后经过编辑的结果,。这里有趣的是你可以看到编译器为 TCHAR字符串 "This is a TCHAR string" 生成了两个字符串($SG1883 and $SG2266),即使它们有相同的内容。然而,此处针对 S"This is a String literal" 仅有一个托管字符串 文字量 ($StringLiteralTok$70000001$),它被使用了两次。大多数程序员调用 "uniquification” 进程,但是 出于某种原因微软的家伙们(Redmondtonians)称之为“字符串暂留”(string interning)”。正如说明文档所描述的:“公共语言基础架构(CLI)确保涉及具有相同字符序列的两个元数据符号的两个 ldstr 指令的结果精确地返回相同字符串对象。” _stprintf(msg, _T("Test 1: Allocate %d strings using LPCTSTR"),num); ShowTime st(msg); for (int i=0; i |
![]() Paul DiLascia 是自由作者,顾问,和 Web/UI整体设计师。他是 Windows++: Writing Reusable Windows Code in C++ (Addison-Wesley, 1992)一书的作者。你可以通过 paul 取得联系。 |