




已阅读5页,还剩960页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第一章 对程序的错误处理第二章 Unicode第三章 内核对象第四章 进程第五章 作业第六章 进程的基本知识第七章 进程的调度、优先级和亲缘性第八章 用户方式中线程的同步第九章 线程与内核对象的同步第十章 线程同步工具包第十一章 线程池的使用第十二章 纤程第十三章 Windows内存结构第十四章 虚拟内存第十五章 在应用程序中使用虚拟内存第十六章 线程的堆栈第十七章 内存映射文件第十八章 堆栈第十九章 DLL基础第二十章 DLL高级操做技术第二十一章 线程本地存储器第二十二章 插入DLL和持接API第二十三章 结束处理程序第二十四章 异常处理程序和软件异常第二十五章 窗口消息第二十六章 硬件输入模型和局部输入状态第一部分 程序员必读第1章 对程序错误的处理在开始介绍Microsoft Windows 的特性之前,必须首先了解Windows的各个函数是如何进行错误处理的。 当调用一个Windows函数时,它首先要检验传递给它的的各个参数的有效性,然后再设法执行任务。如果传递了一个无效参数,或者由于某种原因无法执行这项操作,那么操作系统就会返回一个值,指明该函数在某种程度上运行失败了。表1 - 1列出了大多数Windows函数使用的返回值的数据类型。 表1-1 Wi n d o w s 函数常用的返回值类型 数据类型 表示失败的值 V O I D 该函数的运行不可能失败。Wi n d o w s 函数的返回值类型很少是V O I D B O O L如果函数运行失败,那么返回值是0 ,否则返回的是非0 值。最好对返回值进行测试,以确定它是0 还是非0 。不要测试返回值是否为T R U E H A N D L E如果函数运行失败,则返回值通常是N U L L ,否则返回值为H A N D L E ,用于标识你可以操作的一个对象。注意,有些函数会返回一个句柄值I N VALID_ HANDLE_VA L U E ,它被定义为- 1 。函数的Platform SDK 文档将会清楚地说明该函数运行失败时返回的是N U L L 还是I N VA L I D _ H A N D L E _ VA L I D P V O I D如果函数运行失败,则返回值是N U L L ,否则返回P V O I D ,以标识数据块的内存地址 L O N G / D W O R D 这是个难以处理的值。返回数量的函数通常返回L O N G 或D W O R D 。如果由于某种原因,函数无法对想要进行计数的对象进行计数,那么该函数通常返回0 或- 1 (根据函数而定)。如果调用的函数返回了L O N G / D W O R D ,那么请认真阅读Platform SDK文档,以确保能正确检查潜在的错误一个Wi n d o w s 函数返回的错误代码对了解该函数为什么会运行失败常常很有用。M i c r o s o f t公司编译了一个所有可能的错误代码的列表,并且为每个错误代码分配了一个3 2 位的号码。从系统内部来讲,当一个Wi n d o w s 函数检测到一个错误时,它会使用一个称为线程本地存储器(thread-local storage )的机制,将相应的错误代码号码 与调用的线程关联起来(线程本地存储器将在第2 1 章中介绍)。这将使线程能够互相独立地运行,而不会影响各自的错误代码。当函数返回时,它的返回值 就能指明一个错误已经发生。若要确定这是个什么错误,请调用G e t L a s t E r r o r 函数:DWORD GetLastError();该函数只返回线程的3 2 位错误代码。 当你拥有3 2 位错误代码的号码时,必须将该号码转换成更有用的某种对象。Wi n E r r o r. h 头文件包含了M i c r o s o f t 公司定义的错误代码的列 表。下面显示了该列表的某些内容,使你能够看到它的大概样子: / MessageId: ERROR_SUCCESS/ MessageText:/ The operation completed successfully./#define ERROR_SUCCESS 0L#define NO_ERROR 0L / dderror/ MessageId: ERROR_INVALID_FUNCTION/ MessageText:/ Incorrect function./#define ERROR_INVALID_FUNCTION 1L / dderror/ MessageId: ERROR_FILE_NOT_FOUND/ MessageText:/ The system cannot find the file specified./#define ERROR_FILE_NOT_FOUND 2L/ MessageId: ERROR_PATH_NOT_FOUND/ MessageText:/ The system cannot find the path specified./#define ERROR_PATH_NOT_FOUND 3L/ MessageId: ERROR_TOO_MANY_OPEN_FILES/ MessageText:/ The system cannot open the file./#define ERROR_TOO_MANY_OPEN_FILES 4L/ MessageId: ERROR_ACCESS_DENIED/ MessageText:/ Access is denied./#define ERROR_ACCESS_DENIED 5L如你所见,每个错误都有3 种表示法:一个消息I D (这是你可以在源代码中使用的一个宏,以便与G e t L a s t E r r o r 的返回值进行比较),消息文本(对错误的英文描述)和一个号码(应该避免使用这个号码,可使用消息I D )。请记住,这里只显示了Wi n E r r o r. h 头文件中的很少一部分内容,整个文件的长度超过2 1 0 0 0 行。 当Wi n d o w s 函数运行失败时,应该立即调用G e t L a s t E r r o r 函数。如果调用另一个Wi n d o w s 函数,它的值很可能被改写。 注意G e t L a s t E r r o r 能返回线程产生的最后一个错误。如果该线程调用的Wi n d o w s 函数运行成功,那么最后一个错误代码就不被改写,并且不指明运行成功。有少数Wi n d o w s 函数并不遵循这一规则,它会更改最后的错误代码;但是Platform SDK 文档通常指明,当函数运行成功时,该函数会更改最后的错误代码。 Wi n d o w s 9 8 许多Windows 98 的函数实际上是用M i c r o s o f t 公司的1 6 位Windows 3.1 产品产生的1 6 位代码来实现的。这种比较老的代码并 不通过G e t L a s t E r r o r 之类的函数来报告错误,而且M i c r o s o f t 公司并没有在Windows 98 中修改1 6 位代码,以支持这种错误处理方式 。对于我们来说,这意味着Windows 98 中的许多Wi n 3 2 函数在运行失败时不能设置最后的错误代码。该函数将返回一个值,指明运行失败,这样你就能够 发现该函数确实已经运行失败,但是你无法确定运行失败的原因。 有些Wi n d o w s 函数之所以能够成功运行,其中有许多原因。例如,创建指明的事件内核对象之所以能够取得成功,是因为你实际上创建了该对象,或者因为已经存在带有相同名字的事件内核对象。你应搞清楚成功的原因。为了将该信息返回,M i c r o s o f t 公司选择使用最后错误代码机制。这样,当某些函数运行成功时,就能够通过调用G e t L a d t E r r o r 函数来确定其他的一些信息。对于具有这种行为特性的函数来说,Platform SDK 文档清楚地说明了G e t L a s t E r r o r 函数可以这样使用。请参见该文档,找出C r e a t e E v e n t 函数的例子。 进行调试的时候,监控线程的最后错误代码是非常有用的。在Microsoft Visual studio 6.0 中,M i c r o s o f t 的调试程序支持一个非常有用的特性,即可以配置Wa t c h 窗口,以便始终都能显示线程的最后错误代码的号码和该错误的英文描述。通过选定Wa t c h 窗口中的一行,并键入“ e r r, h r ”,就能够做到这一点。观察图1 - 1 ,你会看到已经调用了C r e a t e F i l e 函数。该函数返回I N VA L I D _ H A N D L E _ VA L U E (- 1 )的H A N D L E ,表示它未能打开指定的文件。但是Wa t c h 窗口向我们显示最后错误代码(即如果调用G e t L a s t E r r o r 函数,该函数返回的错误代码)是0 x 0 0 0 0 0 0 0 2 。该Wa t c h 窗口又进一步指明错误代码2 是指“系统不能找到指定的文件。”你会发现它与Wi n E r r o r. h 头文件中的错误代码2 所指的字符串是相同的。 图1-1 在Visual Studio 6.0 的Wa t c h 窗口中键入“ e r r, h r ”,就可以查看当前线程的最后错误代码 Visual studio 还配有一个小的实用程序,称为Error Lookup 。可以使用Error Lookup将错误代码的号码转换成相应文本描述(见图1 - 2 )。 图1-2 Error Lookup 窗口 如果在编写的应用程序中发现一个错误,可能想要向用户显示该错误的文本描述。Wi n d o w s 提供了一个函数,可以将错误代码转换成它的文本描述。该函数称为FormatMessage,显示如下: DWORD FormatMessage( DWORD dwFlags, / source and processing options LPCVOID lpSource, / pointer to message source DWORD dwMessageId, / requested message identifier DWORD dwLanguageId, / language identifier for requested message LPTSTR lpBuffer, / pointer to message buffer DWORD nSize, / maximum size of message buffer va_list *Arguments / pointer to array of message inserts);F o r m a t M e s s a g e 函数的功能实际上是非常丰富的,在创建向用户显示的字符串信息时,它是首选函数。该函数之所以有这样大的作用,原因之一 是它很容易用多种语言进行操作。该函数能够检测出用户首选的语言(在Regional Settings Control Panel 小应用程序中设定),并返回相应的文本。当然 ,首先必须自己转换字符串,然后将已转换的消息表资源嵌入你的. e x e 文件或D L L 模块中,然后该函数会选定正确的嵌入对象。E r r o r S h o w 示 例应用程序(本章后面将加以介绍)展示了如何调用该函数,以便将M i c r o s o f t 公司定义的错误代码转换成它的文本描述。 有些人常常问我,M i c r o s o f t 公司是否建立了一个主控列表,以显示每个Wi n d o w s 函数可能返回的所有错误代码。可惜,回答是没有这样的列 表,而且M i c r o s o f t 公司将永远不会建立这样的一个列表。因为在创建系统的新版本时,建立和维护该列表实在太困难了。 建立这样一个列表存在的问题是,你可以调用一个Wi n d o w s 函数,但是该函数能够在内部调用另一个函数,而这另一个函数又可以调用另一个函数,如 此类推。由于各种不同的原因,这些函数中的任何一个函数都可能运行失败。有时,当一个函数运行失败时,较高级的函数对它进行恢复,并且仍然可以执行 你想执行的操作。为了创建该主控列表,M i c r o s o f t 公司必须跟踪每个函数的运行路径,并建立所有可能的错误代码的列表。这项工作很困难。而且 ,当创建系统的新版本时,这些函数的运行路径还会改变。 1.1 定义自己的错误代码 前面已经说明Wi n d o w s 函数是如何向函数的调用者指明发生的错误,你也能够将该机制用于自己的函数。比如说,你编写了一个希望其他人调用的函数,你的函数可能因为这样或那样的原因而运行失败,你必须向函数的调用者说明它已经运行失败。 若要指明函数运行失败,只需要设定线程的最后的错误代码,然后让你的函数返回FA L S E 、I N VA L I D _ H A N D L E _ VA L U E 、N U L L 或者返回任何合适的信息。若要设定线程的最后错误代码,只需调用下面的代码: 请将你认为合适的任何3 2 位号码传递给该函数。尝试使用Wi n E r r o r. h 中已经存在的代码, VOID SetLastError(DWORD dwErrCode);只要该代码能够正确地指明想要报告的错误即可。如果你认为Wi n E r r o r. h 中的任何代码都不能正确地反映该错误的性质,那么可以创建你自己的代码 。错误代码是个3 2 位的数字,划分成表1-2所示的各个域。 表1-2 错误代码的域位3 1 3029282716150内容严重性M i c r o s o f t/客户保留设备代码异常代码含义0 =成功0 =M i c r o s o f t公司定义的代码必须是0由M i c r o s o f t公司定义由Microsoft/客户定义1 =供参考1 =客户定义的代码2 =警告3 =错误这些域将在第2 4 章中详细讲述。现在,需要知道的重要域是第2 9 位。M i c r o s o f t 公司规定,他们建立的所有错误代码的这个信息位均使用0 。如果创建自己的错误代码,必须使2 9 位为1 。这样,就可以确保你的错误代码与M i c r o s o f t 公司目前或者将来定义的错误代码不会发生冲突。 1.2 ErrorShow示例应用程序 E r r o r S h o w 应用程序“01 ErrorShow. e x e ”(在清单1 - 1 中列出)展示了如何获取错误代码的文本描述的方法。该应用程序的源代码和资源文件位于本书所附光盘上的0 1 - E r r o r S h o w 目录下。一般来说,该应用程序用于显示调试程序的Wa t c h 窗口和Error Lookup 程序是如何运行的。当启动该程序时,就会出现如图1 - 3 所示的窗口。 图1-3 Error Show 窗口 可以将任何错误代码键入该编辑控件。当单击Look up 按钮时,在底部的滚动窗口中就会显示该错误的文本描述。该应用程序唯一令人感兴趣的特性是如何调用F o r m a t M e s s a g e 函数。下面是使用该函数的方法: /Get the error code DWORD dwError = GetDlgItemInt(hwnd, IDC_ERRORCODE, NULL, FALSE); /Buffer that gets the error message string HLOCAL hlocal = NULL; /Get the error codes textual description BOOL fOk = FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, dwError, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), (PTSTR)&hlocal, 0, NULL); . . . if (hlocal != NULL) SetDlgItemText(hwnd, IDC_ERRORTEXT, (PCTSTR)LocalLock(hlocal); LocalFree(hlocal); else SetDlgItemText(hwnd, IDC_ERRORTEXT, TEXT(Error number not found.);第一个代码行用于从编辑控件中检索错误代码的号码。然后,建立一个内存块的句柄并将它初始化为N U L L 。F o r m a t M e s s a g e 函数在内部对内存块进行分配,并将它的句柄返回给我们。 当调用F o r m a t M e s s a g e 函数时,传递了F O R M AT _ M E S S A G E _ F R O M _ S Y S T E M 标志。该标志告诉F o r m a t M e s s a g e 函数,我们想要系统定义的错误代码的字符串。还传递了F O R M AT _M E S S A G E _ A L L O C AT E _ B U F F E R 标志,告诉该函数为错误代码的文本描述分配足够大的内存块。该内存块的句柄将在h l o c a l 变量中返回。第三个参数指明想要查找的错误代码的号码,第四个参数指明想要文本描述使用什么语言。 如果F o r m a t M e s s a g e 函数运行成功,那么错误代码的文本描述就位于内存块中,将它拷贝到对话框底部的滚动窗口中。如果F o r m a t M e s s a g e 函数运行失败,设法查看N e t M s g . d l l 模块中的消息代码,以了解该错误是否与网络有关。使用N e t M s g . d l l 模块的句柄,再次调用F o r m a t M e s s a g e 函数。你会看到,每个D L L (或. e x e )都有它自己的一组错误代码,可以使用Message Compiler (M C . e x e )将这组错误代码添加给该模块,并将一个资源添加给该模块。这就是Visual Studio 的Error Lookup 工具允许你用M o d u l e s对话框进行的操作。以下是清单1 - 1E r r o r S h o w 示例应用程序。 清单1-1 ErrorShow 示例应用程序/*Module: ErrorShow.cppNotices: Copyright (c) 2000 Jeffrey Richter*/#include .CmnHdr.h /* See Appendix A. */#include #include #include Resource.h/#define ESM_POKECODEANDLOOKUP (WM_USER + 100)const TCHAR g_szAppName = TEXT(Error Show);/BOOL Dlg_OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam) chSETDLGICONS(hwnd, IDI_ERRORSHOW); / Dont accept error codes more than 5 digits long Edit_LimitText(GetDlgItem(hwnd, IDC_ERRORCODE), 5); / Look up the command-line passed error number SendMessage(hwnd, ESM_POKECODEANDLOOKUP, lParam, 0); return(TRUE);/void Dlg_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify) switch (id) case IDCANCEL: EndDialog(hwnd, id); break; case IDC_ALWAYSONTOP: SetWindowPos(hwnd, IsDlgButtonChecked(hwnd, IDC_ALWAYSONTOP) ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); break; case IDC_ERRORCODE: EnableWindow(GetDlgItem(hwnd, IDOK), Edit_GetTextLength(hwndCtl) 0); break; case IDOK: / Get the error code DWORD dwError = GetDlgItemInt(hwnd, IDC_ERRORCODE, NULL, FALSE); HLOCAL hlocal = NULL; / Buffer that gets the error message string / Get the error codes textual description BOOL fOk = FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, dwError, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), (PTSTR) &hlocal, 0, NULL); if (!fOk) / Is it a network-related error? HMODULE hDll = LoadLibraryEx(TEXT(netmsg.dll), NULL, DONT_RESOLVE_DLL_REFERENCES); if (hDll != NULL) FormatMessage( FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_FROM_SYSTEM, hDll, dwError, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), (PTSTR) &hlocal, 0, NULL); FreeLibrary(hDll); if (hlocal != NULL) SetDlgItemText(hwnd, IDC_ERRORTEXT, (PCTSTR) LocalLock(hlocal); LocalFree(hlocal); else SetDlgItemText(hwnd, IDC_ERRORTEXT, TEXT(Error number not found.); break; /INT_PTR WINAPI Dlg_Proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) switch (uMsg) chHANDLE_DLGMSG(hwnd, WM_INITDIALOG, Dlg_OnInitDialog); chHANDLE_DLGMSG(hwnd, WM_COMMAND, Dlg_OnCommand); case ESM_POKECODEANDLOOKUP: SetDlgItemInt(hwnd, IDC_ERRORCODE, (UINT) wParam, FALSE); FORWARD_WM_COMMAND(hwnd, IDOK, GetDlgItem(hwnd, IDOK), BN_CLICKED, PostMessage); SetForegroundWindow(hwnd); break; return(FALSE);/int WINAPI _tWinMain(HINSTANCE hinstExe, HINSTANCE, PTSTR pszCmdLine, int) HWND hwnd = FindWindow(TEXT(#32770), TEXT(Error Show); if (IsWindow(hwnd) / An instance is already running, activate it and send it the new # SendMessage(hwnd, ESM_POKECODEANDLOOKUP, _ttoi(pszCmdLine), 0); else DialogBoxParam(hinstExe, MAKEINTRESOURCE(IDD_ERRORSHOW), NULL, Dlg_Proc, _ttoi(pszCmdLine); return(0);/ End of File /ErrorShow.rc Microsoft Developer Studio generated resource script./#include resource.h#define APSTUDIO_READONLY_SYMBOLS/ Generated from the TEXTINCLUDE 2 resource./#include afxres.h/#undef APSTUDIO_READONLY_SYMBOLS/ English (U.S.) resources#if !defined(AFX_RESOURCE_DLL) | defined(AFX_TARG_ENU)#ifdef _WIN32LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US#pragma code_page(1252)#endif /_WIN32/ Dialog/IDD_ERRORSHOW DIALOGEX 0, 0, 182, 42STYLE DS_SETFOREGROUND | DS_3DLOOK | DS_CENTER | WS_MINIMIZEBOX | WS_VISIBLE | WS_CAPTION | WS_SYSMENUCAPTION Error ShowFONT 8, MS Sans SerifBEGIN LTEXT Error:,IDC_STATIC,4,4,19,8 EDITTEXT IDC_ERRORCODE,24,2,24,14,ES_AUTOHSCROLL | ES_NUMBER DEFPUSHBUTTON Look up,IDOK,56,2,36,14 CONTROL &On top,IDC_ALWAYSONTOP,Button,BS_AUTOCHECKBOX | WS_TABSTOP,104,4,38,10 EDITTEXT IDC_ERRORTEXT,4,20,176,20,ES_MULTILINE | ES_AUTOVSCROLL | ES_READONLY | NOT WS_BORDER | WS_VSCROLL, WS_EX_CLIENTEDGEEND/ DESIGNINFO/#ifdef APSTUDIO_INVOKEDGUIDELINES DESIGNINFO DISCARDABLE BEGIN IDD_ERRORSHOW, DIALOG BEGIN LEFTMARGIN, 7 RIGHTMARGIN, 175 TOPMARGIN, 7 BOTTOMMARGIN, 35 ENDEND#endif / APSTUDIO_INVOKED#ifdef APSTUDIO_INVOKED/ TEXTINCLUDE/1 TEXTINCLUDE DISCARDABLE BEGIN resource.h0END2 TEXTINCLUDE DISCARDABLE BEGIN #include afxres.hrn 0END3 TEXTINCLUDE DISCARDABLE BEGIN rn 0END#endif / APSTUDIO_INVOKED/ Icon/ Icon with lowest ID value placed first to ensure application icon/ remains consistent on all systems.IDI_ERRORSHOW ICON DISCARDABLE ErrorShow.ico#endif / English (U.S.) resources/#ifndef APSTUDIO_INVOKED/ Generated from the TEXTINCLUDE 3 resource./#endif / not APSTUDIO_INVOKED第2章 U n i c o d e随着M i c r o s o f t 公司的Wi n d o w s 操作系统在全世界日益广泛的流行,对于软件开发人员来说,将目标瞄准国际上的各个不同市场,已经成为一个越来越重要的问题。美国的软件版本比国际版本提前6 个月推向市场,这曾经是个司空见惯的现象。但是,由于各国对Wi n d o w s 操作系统提供了越来越多的支持,因此就更加容易为国际市场生产各种应用软件,从而缩短了软件的美国版本与国际版本推出的时间间隔。 Wi n d o w s 操作系统始终不逾地提供各种支持,以帮助软件开发人员进行应用程序的本地化工作。应用软件可以从各种不同的函数中获得特定国家的信息,并可观察控制面板的设置,以确定用户的首选项。Wi n d o w s 甚至支持不同的字体,以适应应用的需要。 之所以将这一章放在本书的开头,是因为考虑到U n i c o d e 是开发任何应用程序时要采用的基本步骤。本书的每一章中几乎都要讲到关于U n i c o d e 的问题,而且书中给出的所有示例应用程序都是“用U n i c o d e 实现的”。如果你为Microsoft Windows 2000 或Microsoft Windows CE 开发应用程序,你应该使用U n i c o d e 进行开发。如果你为Microsoft Windows 98 开发应用程序,你必须对某些问题作出决定。本章也要讲述Windows 98 的有关问题。 2.1 字符集 软件的本地化要解决的真正问题,实际上就是如何来处理不同的字符集。多年来,许多人一直将文本串作为一系列单字节字符来进行编码,并在结尾处放上一个零。对于我们来说,这已经成了习惯。当调用s t r l e n 函数时,它在以0 结尾的单字节字符数组中返回字符的数目。 问题是,有些文字和书写规则(比如日文中的汉字就是个典型的例子)的字符集中的符号太多了,因此单字节(它提供的符号最多不能超过2 5 6 个)是根本不敷使用的。为此出现了双字节字符集(D B C S ),以支持这些文字和书写规则。 2.1.1 单字节与双字节字符集 在双字节字符集中,字符串中的每个字符可以包含一个字节或包含两个字节。例如,日文中的汉字,如果第一个字符在0 x 8 1 与0 x 9 F 之间,或者在0 x E 0 与0 x F C 之间,那么就必须观察下一个字节,才能确定字符串中的这个完整的字符。使用双字节字符集,对于程序员来说简直是个很大的难题,因为有些字符只有一个字节宽,而有些字符则是两个字节宽。 如果只是调用s t r l e n 函数,那么你无法真正了解字符串中究竟有多少字符,它只能告诉你到达结尾的0 之前有多少个字节。A N S I 的C 运行期库中没有配备相应的函数,使你能够对双字节字符集进行操作。但是,Microsoft Visual C+的运行期库却包含许多函数,如_ m b s l e n ,它可以用来操作多字节(既包括单字节也包括双字节)字符串。 为了帮助你对D B C S 字符串进行操作,Wi n d o w s 提供了下面的一组帮助函数(见表2 - 1 )。前两个函数CharNext 和Char Prev 允许前向或逆向遍历DBCS 字符串,方法是每次一个字符。第三个函数IsDBCSLeadByte, 在字节返回到一个两字字节符的第一个字节时将返回T R U E 。 表2-1 对D B C S 字符串进行操作的帮助函数 函数描述PTSTR CharNext(PCTSTR pszCurrentChar);返回字符串中的下一个字符的地址PTSTR CharPrev (PCTSTR pszStart,PCTSTR p s z C u r r e n t C h a r);返回字符串中的上一个字符的地址BOOL IsDBCSLeadByteTRUE(BYTE bTestChar);如果该字节是DBCS 字符的第一个字节,则返回 尽管这些函数使得我们对D B C S 的操作更容易,但还需要,一个更好的方法让我们来看看U n i c o d e 。2.1.2 Unicode :宽字节字符集 U n i c o d e 是A p p l e 和X e r o x 公司于1 9 8 8 年建立的一个技术标准。1 9 9 1 年,成立了一个集团机构负责U n i c o d e 的开发和推广应用。该集团由A p p l e 、C o m p a q 、H P 、I B M 、M i c r o s o f t 、O r a c l e 、Silicon Graphics, Inc.、S y b a s e 、U n i s y s 和X e r o x 等公司组成(若要了解该集团的全部成员,请通过网址w w w. U n i c o d e . o rg 查找)。该集团负责维护U n i c o d e 标准。U n i c o d e 的完整描述可以参阅A d d i s o n We s l e y 出版的Unicode Standard 一书(该书可以通过网址w w w. U n i c o d e . o rg 订购)。 U n i c o d e 提供了一种简单而又一致的表示字符串的方法。U n i c o d e 字符串中的所有字符都是1 6 位的(两个字节)。它没有专门的字节来指明下一个字节是属于同一个字符的组成部分,还是一个新字符。这意味着你只需要对指针进行递增或递减,就可以遍历字符串中的各个字符,不再需要调用C h a r N e x t 、C h a r P r e v 和I s D B C S L e a d B y t e 之类的函数。 由于U n i c o d e 用一个1 6 位的值来表示每个字符,因此总共可以得到65 000 个字符,这样,它就能够对世界各国的书面文字中的所有字符进行编码,远远超过了单字节字符集的2 5 6 个字符的数目。 目前,已经为阿拉伯文、中文拼音、西里尔字母(俄文)、希腊文、西伯莱文、日文、韩文和拉丁文(英文)字母定义了U n i c o d e 代码点。(代码点是字符集中符号的位置。)这些字符集中还包含了大量的标点符号、数学符号、技术符号、箭头、装饰标志、区分标志和其他许多字符。如果将所有这些字母和符号加在一起,总计约达3 5 0 0 0 个不同的代码点,这样,总计65 000 多个代码点中,大约还有一半可供将来扩充时使用。 这65536个字符可以分成不同的区域。表2-2 显示了这样的区域的一部分以及分配给这些区域的字符。 表2-2 区域字符 1 6 位代码字符16 位代码字符0 0
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 中信银行上海市松江区2025秋招笔试价值观测评题专练及答案
- 2025年执业药师之《药事管理与法规》试题及参考答案详解【满分必刷】
- 浦发银行临沂市沂水县2025秋招笔试行测高频题及答案
- 广发银行台州市仙居县2025秋招数据分析师笔试题及答案
- 招商银行南通市海安市2025秋招笔试综合模拟题库及答案
- 华夏银行上海市静安区2025秋招无领导模拟题角色攻略
- 民生银行贵阳市乌当区2025秋招半结构化面试15问及话术
- 中信银行重庆市沙坪坝区2025秋招小语种岗笔试题及答案
- 中信银行厦门市思明区2025秋招群面案例总结模板
- 招商银行太原市小店区2025秋招信息科技岗笔试题及答案
- 2024版2025秋贵州黔教版综合实践活动五年级上册全册教案教学设计
- 转作风重实干课件
- 村干部饮水安全培训总结课件
- 安全生产治本攻坚三年行动半年工作总结
- 单招备考科学方案
- 医美咨询培训课件
- 海船船员适任 评估规范(2024)轮机专业
- DB50-T 1463.2-2023 牛羊布鲁氏菌病防控技术规范 第2部分:人员防护
- NoSQL数据库应用与实践 课件 第1-6章 认识NoSQL - 增删改查
- 20世纪宋史研究:主要趋势、热点领域与未来展望
- 2025年度餐饮店知识产权保护与合伙人合同
评论
0/150
提交评论