收藏 分享(赏)

Win32字符编码.doc

上传人:scg750829 文档编号:8090112 上传时间:2019-06-08 格式:DOC 页数:11 大小:102.50KB
下载 相关 举报
Win32字符编码.doc_第1页
第1页 / 共11页
Win32字符编码.doc_第2页
第2页 / 共11页
Win32字符编码.doc_第3页
第3页 / 共11页
Win32字符编码.doc_第4页
第4页 / 共11页
Win32字符编码.doc_第5页
第5页 / 共11页
点击查看更多>>
资源描述

1、C+字 符 串 完 全 指 引 之 一 Win32 字 符 编 码原 著 : Michael Dunn翻 译 : Chengjie Sun原 文 出 处 : CodeProject: The Complete Guide to C+ Strings, Part I引 言毫 无 疑 问 , 我 们 都 看 到 过 像 TCHAR, std:string, BSTR 等 各 种 各 样 的 字 符串 类 型 , 还 有 那 些 以 _tcs 开 头 的 奇 怪 的 宏 。 你 也 许 正 在 盯 着 显 示 器 发 愁 。 本 指 引将 总 结 引 进 各 种 字 符 类 型 的 目 的 , 展

2、示 一 些 简 单 的 用 法 , 并 告 诉 您 在 必 要 时 , 如 何实 现 各 种 字 符 串 类 型 之 间 的 转 换 。在 第 一 部 分 , 我 们 将 介 绍 3 种 字 符 编 码 类 型 。 了 解 各 种 编 码 模 式 的 工 作 方 式 是很 重 要 的 事 情 。 即 使 你 已 经 知 道 一 个 字 符 串 是 一 个 字 符 数 组 , 你 也 应 该 阅 读 本 部 分 。一 旦 你 了 解 了 这 些 , 你 将 对 各 种 字 符 串 类 型 之 间 的 关 系 有 一 个 清 楚 地 了 解 。在 第 二 部 分 , 我 们 将 单 独 讲 述 s

3、tring 类 , 怎 样 使 用 它 及 实 现 他 们 相 互 之 间 的转 换 。字 符 基 础 - ASCII, DBCS, Unicode所 有 的 string 类 都 是 以 C-style 字 符 串 为 基 础 的 。 C-style 字 符 串 是 字 符 数组 。 所 以 我 们 先 介 绍 字 符 类 型 。 这 里 有 3 种 编 码 模 式 对 应 3 种 字 符 类 型 。 第 一 种编 码 类 型 是 单 子 节 字 符 集 ( single-byte character set or SBCS) 。 在 这 种 编 码 模式 下 , 所 有 的 字 符 都 只

4、 用 一 个 字 节 表 示 。 ASCII 是 SBCS。 一 个 字 节 表 示 的 0 用来 标 志 SBCS 字 符 串 的 结 束 。第 二 种 编 码 模 式 是 多 字 节 字 符 集 ( multi-byte character set or MBCS) 。 一个 MBCS 编 码 包 含 一 些 一 个 字 节 长 的 字 符 , 而 另 一 些 字 符 大 于 一 个 字 节 的 长 度 。 用在 Windows 里 的 MBCS 包 含 两 种 字 符 类 型 , 单 字 节 字 符 ( single-byte characters) 和 双 字 节 字 符 ( doub

5、le-byte characters) 。 由 于 Windows 里 使 用的 多 字 节 字 符 绝 大 部 分 是 两 个 字 节 长 , 所 以 MBCS 常 被 用 DBCS 代 替 。在 DBCS 编 码 模 式 中 , 一 些 特 定 的 值 被 保 留 用 来 表 明 他 们 是 双 字 节 字 符 的 一 部分 。 例 如 , 在 Shift-JIS 编 码 中 ( 一 个 常 用 的 日 文 编 码 模 式 ) , 0x81-0x9f 之 间和 0xe0-oxfc 之 间 的 值 表 示 “这 是 一 个 双 字 节 字 符 , 下 一 个 子 节 是 这 个 字 符 的

6、一 部分 。 “这 样 的 值 被 称 作 “leading bytes“,他 们 都 大 于 0x7f。 跟 随 在 一 个 leading byte 子 节 后 面 的 字 节 被 称 作 “trail byte“。 在 DBCS 中 , trail byte 可 以 是 任 意 非0 值 。 像 SBCS 一 样 , DBCS 字 符 串 的 结 束 标 志 也 是 一 个 单 字 节 表 示 的 0。第 三 种 编 码 模 式 是 Unicode。 Unicode 是 一 种 所 有 的 字 符 都 使 用 两 个 字 节 编 码的 编 码 模 式 。 Unicode 字 符 有 时

7、也 被 称 作 宽 字 符 , 因 为 它 比 单 子 节 字 符 宽 ( 使 用 了更 多 的 存 储 空 间 ) 。 注 意 , Unicode 不 能 被 看 作 MBCS。 MBCS 的 独 特 之 处 在 于它 的 字 符 使 用 不 同 长 度 的 字 节 编 码 。 Unicode 字 符 串 使 用 两 个 字 节 表 示 的 0 作为 它 的 结 束 标 志 。单 字 节 字 符 包 含 拉 丁 文 字 母 表 , accented characters 及 ASCII 标 准 和 DOS操 作 系 统 定 义 的 图 形 字 符 。 双 字 节 字 符 被 用 来 表 示

8、东 亚 及 中 东 的 语 言 。 Unicode被 用 在 COM 及 Windows NT 操 作 系 统 内 部 。你 一 定 已 经 很 熟 悉 单 字 节 字 符 。 当 你 使 用 char 时 , 你 处 理 的 是 单 字 节 字 符 。双 字 节 字 符 也 用 char 类 型 来 进 行 操 作 ( 这 是 我 们 将 会 看 到 的 关 于 双 子 节 字 符 的 很多 奇 怪 的 地 方 之 一 ) 。 Unicode 字 符 用 wchar_t 来 表 示 。 Unicode 字 符 和 字 符 串常 量 用 前 缀 L 来 表 示 。 例 如 :wchar_t w

9、ch = L1; / 2 bytes, 0x0031wchar_t* wsz = L“Hello“; / 12 bytes, 6 wide characters字 符 在 内 存 中 是 怎 样 存 储 的单 字 节 字 符 串 : 每 个 字 符 占 一 个 字 节 按 顺 序 依 次 存 储 , 最 后 以 单 字 节 表 示 的 0结 束 。 例 如 。 “Bob“的 存 贮 形 式 如 下 :42 6F 62 00B o b BOSUnicode 的 存 储 形 式 , L“Bob“42 00 6F 00 62 00 00 00B o b BOS使 用 两 个 字 节 表 示 的 0

10、来 做 结 束 标 志 。一 眼 看 上 去 , DBCS 字 符 串 很 像 SBCS 字 符 串 , 但 是 我 们 一 会 儿 将 看 到 DBCS 字 符 串 的 微 妙 之 处 , 它 使 得 使 用 字 符 串 操 作 函 数 和 永 字 符 指 针 遍 历 一 个 字 符串 时 会 产 生 预 料 之 外 的 结 果 。 字 符 串 “ “ (“nihongo“)在 内 存 中 的 存 储 形 式 如 下( LB 和 TB 分 别 用 来 表 示 leading byte 和 trail byte)93 FA 96 7B 8C EA 00LB TB LB TB LB TB EOS

11、EOS值 得 注 意 的 是 , “ni“的 值 不 能 被 解 释 成 WORD 型 值 0xfa93, 而 应 该 看 作 两 个 值93 和 fa 以 这 种 顺 序 被 作 为 “ni“的 编 码 。使 用 字 符 串 处 理 函 数我 们 都 已 经 见 过 C 语 言 中 的 字 符 串 函 数 , strcpy(), sprintf(), atoll()等 。 这些 字 符 串 只 应 该 用 来 处 理 单 字 节 字 符 字 符 串 。 标 准 库 也 提 供 了 仅 适 用 于Unicode 类 型 字 符 串 的 函 数 , 比 如 wcscpy(), swprintf(

12、), wtol()等 。微 软 还 在 它 的 CRT(C runtime library)中 增 加 了 操 作 DBCS 字 符 串 的 版 本 。Str*()函 数 都 有 对 应 名 字 的 DBCS 版 本 _mbs*()。 如 果 你 料 到 可 能 会 遇 到DBCS 字 符 串 ( 如 果 你 的 软 件 会 被 安 装 在 使 用 DBCS 编 码 的 国 家 , 如 中 国 , 日 本等 , 你 就 可 能 会 ) , 你 应 该 使 用 _mbs*()函 数 , 因 为 他 们 也 可 以 处 理 SBCS 字符 串 。 ( 一 个 DBCS 字 符 串 也 可 能 含

13、有 单 字 节 字 符 , 这 就 是 为 什 么 _mbs*()函 数 也 能 处 理 SBCS 字 符 串 的 原 因 )让 我 们 来 看 一 个 典 型 的 字 符 串 来 阐 明 为 什 么 需 要 不 同 版 本 的 字 符 串 处 理 函 数 。我 们 还 是 使 用 前 面 的 Unicode 字 符 串 L“Bob“:42 00 6F 00 62 00 00 00B o b BOS因 为 x86CPU 是 little-endian, 值 0x0042 在 内 存 中 的 存 储 形 式 是 42 00。你 能 看 出 如 果 这 个 字 符 串 被 传 给 strlen()

14、函 数 会 出 现 什 么 问 题 吗 ? 它 将 先 看 到 第 一个 字 节 42, 然 后 是 00, 而 00 是 字 符 串 结 束 的 标 志 , 于 是 strlen()将 会 返 回 1。如 果 把 “Bob“传 给 wcslen(), 将 会 得 出 更 坏 的 结 果 。 wcslen()将 会 先 看 到0x6f42, 然 后 是 0x0062, 然 后 一 直 读 到 你 的 缓 冲 区 的 末 尾 , 直 到 发 现 00 00 结束 标 志 或 者 引 起 了 GPF。到 目 前 为 止 , 我 们 已 经 讨 论 了 str*()和 wcs*()的 用 法 及 它

15、 们 之 间 的 区 别 。Str*()和 _mbs*()之 间 的 有 区 别 区 别 呢 ? 明 白 他 们 之 间 的 区 别 , 对 于 采 用 正 确 的方 法 来 遍 历 DBCS 字 符 串 是 很 重 要 的 。 下 面 , 我 们 将 先 介 绍 字 符 串 的 遍 历 , 然 后 回到 str*()与 _mbs*()之 间 的 区 别 这 个 问 题 上 来 。正 确 的 遍 历 和 索 引 字 符 串因 为 我 们 中 大 多 数 人 都 是 用 着 SBCS 字 符 串 成 长 的 , 所 以 我 们 在 遍 历 字 符 串 时 ,常 常 使 用 指 针 的 +-和 -

16、操 作 。 我 们 也 使 用 数 组 下 标 的 表 示 形 式 来 操 作 字 符 串 中 的 字符 。 这 两 种 方 式 是 用 于 SBCS 和 Unicode 字 符 串 , 因 为 它 们 中 的 字 符 有 着 相 同 的宽 度 , 编 译 器 能 正 确 的 返 回 我 们 需 要 的 字 符 。然 而 , 当 碰 到 DBCS 字 符 串 时 , 我 们 必 须 抛 弃 这 些 习 惯 。 这 里 有 使 用 指 针 遍 历DBCS 字 符 串 时 的 两 条 规 则 。 违 背 了 这 两 条 规 则 , 你 的 程 序 就 会 存 在 DBCS 有 关的 bugs。 1

17、 在 前 向 遍 历 时 , 不 要 使 用 +操 作 , 除 非 你 每 次 都 检 查 lead byte; 2 永 远 不 要 使 用 -操 作 进 行 后 向 遍 历 。我 们 先 来 阐 述 规 则 2, 因 为 找 到 一 个 违 背 它 的 真 实 的 实 例 代 码 是 很 容 易 的 。 假设 你 有 一 个 程 序 在 你 自 己 的 目 录 里 保 存 了 一 个 设 置 文 件 , 你 把 安 装 目 录 保 存 在 注 册表 中 。 在 运 行 时 , 你 从 注 册 表 中 读 取 安 装 目 录 , 然 后 合 成 配 置 文 件 名 , 接 着 读 取 该文 件

18、 。 假 设 , 你 的 安 装 目 录 是 C:Program FilesMyCoolApp, 那 么 你 合 成 的 文 件名 应 该 是 C:Program FilesMyCoolAppconfig.bin。 当 你 进 行 测 试 时 , 你 发 现 程序 运 行 正 常 。现 在 , 想 象 你 合 成 文 件 名 的 代 码 可 能 是 这 样 的 :bool GetConfigFileName ( char* pszName, size_t nBuffSize )char szConfigFilenameMAX_PATH;/ Read install dir from regis

19、try. well assume it succeeds./ Add on a backslash if it wasnt present in the registry value./ First, get a pointer to the terminating zero.char* pLastChar = strchr ( szConfigFilename, 0 );/ Now move it back one character.pLastChar-; if ( *pLastChar != )strcat ( szConfigFilename, “ );/ Add on the nam

20、e of the config file.strcat ( szConfigFilename, “config.bin“ );/ If the callers buffer is big enough, return the filename.if ( strlen ( szConfigFilename ) = nBuffSize )return false;elsestrcpy ( pszName, szConfigFilename );return true; 这 是 一 段 很 健 壮 的 代 码 , 然 而 在 遇 到 DBCS 字 符 时 它 将 会 出 错 。 让 我 们 来 看看

21、 为 什 么 。 假 设 一 个 日 本 用 户 使 用 了 你 的 程 序 , 把 它 安 装 在 C: 。 下 面 是这 个 名 字 在 内 存 中 的 存 储 形 式 :43 3A 5C 83 88 83 45 83 52 83 5C 00LB TB LB TB LB TB LB TB C : EOS当 使 用 GetConfigFileName() 检 查 尾 部 的 时 , 它 寻 找 安 装 目 录 名 中 最 后的 非 0 字 节 , 看 它 是 等 于 的 , 所 以 没 有 重 新 增 加 一 个 。 结 果 是 代 码 返 回了 错 误 的 文 件 名 。哪 里 出 错 了

22、 呢 ? 看 看 上 面 两 个 被 用 蓝 色 高 量 显 示 的 字 节 。 斜 杠 的 值 是0x5c。 的 值 是 83 5c。 上 面 的 代 码 错 误 的 读 取 了 一 个 trail byte, 把 它 当 作 了一 个 字 符 。正 确 的 后 向 遍 历 方 法 是 使 用 能 够 识 别 DBCS 字 符 的 函 数 , 使 指 针 移 动 正 确 的字 节 数 。 下 面 是 正 确 的 代 码 。 ( 指 针 移 动 的 地 方 用 红 色 标 明 )bool FixedGetConfigFileName ( char* pszName, size_t nBuffS

23、ize )char szConfigFilenameMAX_PATH;/ Read install dir from registry. well assume it succeeds./ Add on a backslash if it wasnt present in the registry value./ First, get a pointer to the terminating zero.char* pLastChar = _mbschr ( szConfigFilename, 0 );/ Now move it back one double-byte character.pL

24、astChar = CharPrev ( szConfigFilename, pLastChar );if ( *pLastChar != )_mbscat ( szConfigFilename, “ );/ Add on the name of the config file._mbscat ( szConfigFilename, “config.bin“ );/ If the callers buffer is big enough, return the filename.if ( _mbslen ( szInstallDir ) = nBuffSize )return false;el

25、se_mbscpy ( pszName, szConfigFilename );return true;上 面 的 函 数 使 用 CharPrev() API 使 pLastChar 向 后 移 动 一 个 字 符 , 这 个 字 符可 能 是 两 个 字 节 长 。 在 这 个 版 本 里 , if 条 件 正 常 工 作 , 因 为 lead byte 永 远 不 会等 于 0x5c。让 我 们 来 想 象 一 个 违 背 规 则 1 的 场 合 。 例 如 , 你 可 能 要 检 测 一 个 用 户 输 入 的文 件 名 是 否 多 次 出 现 了 :。 如 果 , 你 使 用 +操

26、作 来 遍 历 字 符 串 , 而 不 是 使 用CharNext(), 你 可 能 会 发 出 不 正 确 的 错 误 警 告 如 果 恰 巧 有 一 个 trail byte 它 的 值的 等 于 :的 值 。与 规 则 2 相 关 的 关 于 字 符 串 索 引 的 规 则 :2a. 永 远 不 要 使 用 减 法 去 得 到 一 个 字 符 串 的 索 引 。违 背 这 条 规 则 的 代 码 和 违 背 规 则 2 的 代 码 很 相 似 。 例 如 ,char* pLastChar = 这 和 向 后 移 动 一 个 指 针 是 同 样 的 效 果 。回 到 关 于 str*()和

27、 _mbs*()的 区 别现 在 , 我 们 应 该 很 清 楚 为 什 么 _mbs*()函 数 是 必 需 的 。 Str*()函 数 根 本不 考 虑 DBCS 字 符 , 而 _mbs*()考 虑 。 如 果 , 你 调 用 strrchr(“C: “, ),返 回 结 果 可 能 是 错 误 的 , 然 而 _mbsrchr()将 会 认 出 最 后 的 双 字 节 字 符 , 返 回 一 个指 向 真 的 的 指 针 。关 于 字 符 串 函 数 的 最 后 一 点 : str*()和 _mbs*()函 数 认 为 字 符 串 的 长 度 都是 以 char 来 计 算 的 。 所

28、 以 , 如 果 一 个 字 符 串 包 含 3 个 双 字 节 字 符 , _mbslen()将 会 返 回 6。 Unicode 函 数 返 回 的 长 度 是 按 wchar_t 来 计 算 的 。 例 如 ,wcslen(L“Bob“)返 回 3。Win32 API 中 的 MBCS 和 Unicode两 组 APIs: 尽 管 你 也 许 从 来 没 有 注 意 过 , Win32 中 的 每 个 与 字 符 串 相 关 的 API 和message 都 有 两 个 版 本 。 一 个 版 本 接 受 MBCS 字 符 串 , 另 一 个 接 受 Unicode 字符 串 。 例 如

29、 , 根 本 没 有 SetWindowText()这 个 API, 相 反 , 有SetWindowTextA()和 SetWindowTextW()。 后 缀 A 表 明 这 是 MBCS 函 数 , 后 缀W 表 示 这 是 Unicode 版 本 的 函 数 。当 你 build 一 个 Windows 程 序 , 你 可 以 选 择 是 用 MBCS 或 者 Unicode APIs。 如 果 , 你 曾 经 用 过 VC 向 导 并 且 没 有 改 过 预 处 理 的 设 置 , 那 表 明 你 用 的 是MBCS 版 本 。 那 么 , 既 然 没 有 SetWindowText

30、() API, 我 们 为 什 么 可 以 使 用 它 呢 ?winuser.h 头 文 件 包 含 了 一 些 宏 , 例 如 :BOOL WINAPI SetWindowTextA ( HWND hWnd, LPCSTR lpString );BOOL WINAPI SetWindowTextW ( HWND hWnd, LPCWSTR lpString );#ifdef UNICODE#define SetWindowText SetWindowTextW#else#define SetWindowText SetWindowTextA#endif 当 使 用 MBCS APIs 来 b

31、uild 程 序 时 , UNICODE 没 有 被 定 义 , 所 以 预 处 理 器 看 到 :#define SetWindowText SetWindowTextA这 个 宏 定 义 把 所 有 对 SetWindowText 的 调 用 都 转 换 成 真 正 的 API 函 数SetWindowTextA。 ( 当 然 , 你 可 以 直 接 调 用 SetWindowTextA() 或 者 SetWindowTextW(), 虽 然 你 不 必 那 么 做 。 )所 以 , 如 果 你 想 把 默 认 使 用 的 API 函 数 变 成 Unicode 版 的 , 你 可 以 在

32、 预 处 理器 设 置 中 , 把 _MBCS 从 预 定 义 的 宏 列 表 中 删 除 , 然 后 添 加 UNICODE 和_UNICODE。 (你 需 要 两 个 都 定 义 , 因 为 不 同 的 头 文 件 可 能 使 用 不 同 的 宏 。 ) 然而 , 如 果 你 用 char 来 定 义 你 的 字 符 串 , 你 将 会 陷 入 一 个 尴 尬 的 境 地 。 考 虑 下 面 的代 码 :HWND hwnd = GetSomeWindowHandle();char szNewText = “we love Bob!“;SetWindowText ( hwnd, szNewT

33、ext );在 预 处 理 器 把 SetWindowText 用 SetWindowTextW 来 替 换 后 , 代 码 变 成 :HWND hwnd = GetSomeWindowHandle();char szNewText = “we love Bob!“;SetWindowTextW ( hwnd, szNewText );看 到 问 题 了 吗 ? 我 们 把 单 字 节 字 符 串 传 给 了 一 个 以 Unicode 字 符 串 做 参 数 的函 数 。 解 决 这 个 问 题 的 第 一 个 方 案 是 使 用 #ifdef 来 包 含 字 符 串 变 量 的 定 义 :

34、HWND hwnd = GetSomeWindowHandle();#ifdef UNICODEwchar_t szNewText = L“we love Bob!“;#elsechar szNewText = “we love Bob!“;#endifSetWindowText ( hwnd, szNewText );你 可 能 已 经 感 受 到 了 这 样 做 将 会 使 你 多 么 的 头 疼 。 完 美 的 解 决 方 案 是 使 用TCHAR.使 用 TCHARTCHAR 是 一 种 字 符 串 类 型 , 它 让 你 在 以 MBCS 和 UNNICODE 来 build 程 序

35、时 可 以 使 用 同 样 的 代 码 , 不 需 要 使 用 繁 琐 的 宏 定 义 来 包 含 你 的 代 码 。 TCHAR 的定 义 如 下 :#ifdef UNICODEtypedef wchar_t TCHAR;#elsetypedef char TCHAR;#endif所 以 用 MBCS 来 build 时 , TCHAR 是 char, 使 用 UNICODE 时 , TCHAR 是wchar_t。 还 有 一 个 宏 来 处 理 定 义 Unicode 字 符 串 常 量 时 所 需 的 L 前 缀 。#ifdef UNICODE#define _T(x) L#x#else

36、#define _T(x) x#endif#是 一 个 预 处 理 操 作 符 , 它 可 以 把 两 个 参 数 连 在 一 起 。 如 果 你 的 代 码 中 需 要 字符 串 常 量 , 在 它 前 面 加 上 _T 宏 。 如 果 你 使 用 Unicode 来 build, 它 会 在 字 符 串 常量 前 加 上 L 前 缀 。TCHAR szNewText = _T(“we love Bob!“);像 是 用 宏 来 隐 藏 SetWindowTextA/W 的 细 节 一 样 , 还 有 很 多 可 以 供 你 使 用 的宏 来 实 现 str*()和 _mbs*()等 字 符

37、 串 函 数 。 例 如 , 你 可 以 使 用 _tcsrchr 宏 来替 换 strrchr()、 _mbsrchr()和 wcsrchr()。 _tcsrchr 根 据 你 预 定 义 的 宏 是 _MBCS还 是 UNICODE 来 扩 展 成 正 确 的 函 数 , 就 像 SetWindowText 所 作 的 一 样 。不 仅 str*()函 数 有 TCHAR 宏 。 其 他 的 函 数 如 , _stprintf( 代 替 sprinft()和 swprintf()) ,_tfopen( 代 替 fopen()和 _wfopen()) 。 MSDN 中 “Generic-Te

38、xt Routine Mappings.“标 题 下 有 完 整 的 宏 列 表 。字 符 串 和 TCHAR typedefs由 于 Win32 API 文 档 的 函 数 列 表 使 用 函 数 的 常 用 名 字 ( 例 如 ,“SetWindowText“) , 所 有 的 字 符 串 都 是 用 TCHAR 来 定 义 的 。 ( 除 了 XP 中 引 入的 只 适 用 于 Unicode 的 API) 。 下 面 列 出 一 些 常 用 的 typedefs, 你 可 以 在 msdn中 看 到 他 们 。type Meaning in MBCS builds Meaning in

39、 Unicode buildsWCHAR wchar_t wchar_tLPSTR zero-terminated string of char (char*) zero-terminated string of char (char*)LPCSTR constant zero-terminated string of char (const char*) constant zero-terminated string of char (const char*)LPWSTR zero-terminated Unicode string (wchar_t*) zero-terminated Un

40、icode string (wchar_t*)LPCWSTRconstant zero-terminated Unicode string (const wchar_t*)constant zero-terminated Unicode string (const wchar_t*)TCHAR char wchar_tLPTSTR zero-terminated string of TCHAR (TCHAR*) zero-terminated string of TCHAR (TCHAR*)LPCTSTRconstant zero-terminated string of TCHAR (con

41、st TCHAR*)constant zero-terminated string of TCHAR (const TCHAR*)何 时 使 用 TCHAR 和 Unicode到 现 在 , 你 可 能 会 问 , 我 们 为 什 么 要 使 用 Unicode。 我 已 经 用 了 很 多 年 的char。 下 列 3 种 情 况 下 , 使 用 Unicode 将 会 使 你 受 益 : 1 你 的 程 序 只 运 行 在 Windows NT 系 统 中 。 2 你 的 程 序 需 要 处 理 超 过 MAX_PATH 个 字 符 长 的 文 件 名 。 3 你 的 程 序 需 要 使

42、用 XP 中 引 入 的 只 有 Unicode 版 本 的 API.Windows 9x 中 大 多 数 的 API 没 有 实 现 Unicode 版 本 。 所 以 , 如 果 你 的 程序 要 在 windows 9x 中 运 行 , 你 必 须 使 用 MBCS APIs。 然 而 , 由 于 NT 系 统 内 部都 使 用 Unicode, 所 以 使 用 Unicode APIs 将 会 加 快 你 的 程 序 的 运 行 速 度 。 每 次 ,你 传 递 一 个 字 符 串 调 用 MBCS API, 操 作 系 统 会 把 这 个 字 符 串 转 换 成 Unicode 字符

43、 串 , 然 后 调 用 对 应 的 Unicode API。 如 果 一 个 字 符 串 被 返 回 , 操 作 系 统 还 要 把 它转 变 回 去 。 尽 管 这 个 转 换 过 程 被 高 度 优 化 了 , 但 它 对 速 度 造 成 的 损 失 是 无 法 避 免 的 。只 要 你 使 用 Unicode API, NT 系 统 允 许 使 用 非 常 长 的 文 件 名 ( 突 破 了MAX_PATH 的 限 制 , MAX_PATH=260) 。 使 用 Unicode API 的 另 一 个 优 点 是 你 的程 序 会 自 动 处 理 用 户 输 入 的 各 种 语 言 。

44、 所 以 一 个 用 户 可 以 输 入 英 文 , 中 文 或 者 日 文 ,而 你 不 需 要 额 外 编 写 代 码 去 处 理 它 们 。最 后 , 随 着 windows 9x 产 品 的 淡 出 , 微 软 似 乎 正 在 抛 弃 MBCS APIs。 例 如 ,包 含 两 个 字 符 串 参 数 的 SetWindowTheme() API 只 有 Unicode 版 本 的 。 使 用Unicode 来 build 你 的 程 序 将 会 简 化 字 符 串 的 处 理 , 你 不 必 在 MBCS 和 Unicdoe之 间 相 互 转 换 。即 使 你 现 在 不 使 用 U

45、nicode 来 build 你 的 程 序 , 你 也 应 该 使 用 TCHAR 及 其相 关 的 宏 。 这 样 做 不 仅 可 以 的 代 码 可 以 很 好 地 处 理 DBCS, 而 且 如 果 将 来 你 想 用Unicode 来 build 你 的 程 序 , 你 只 需 要 改 变 一 下 预 处 理 器 中 的 设 置 就 可 以 实 现 了 。作 者 简 介Michael Dunn: 居 住 在 阳 光 城 市 洛 杉 矶 。 他 是 如 此 的 喜 欢 这 里 的 天 气 以 致 于 想一 生 都 住 在 这 里 。 他 在 4 年 级 时 开 始 编 程 , 那 时

46、用 的 电 脑 是 Apple /e。 1995年 , 在 UCLA 获 得 数 学 学 士 学 位 , 随 后 在 Symantec 公 司 做 QA 工 程 师 , 在 Norton AntiVirus 组 工 作 。 他 自 学 了 Windows 和 MFC 编 程 。 1999-2000 年 ,他 设 计 并 实 现 了 Norton AntiVirus 的 新 界 面 。 Michael 现 在 在 Napster( 一 个 提 供 在 线 订 阅 音 乐 服 务 的 公 司 ) 做 开 发 工 作 ,他 还 开 发 了 UltraBar, 一 个 IE 工 具 栏 插 件 , 它 可 以 使 网 络 搜 索 更 加 容 易 , 给 了 googlebar 以 沉 重 打 击 ; 他 还 开 发 了 CodeProject SearchBar; 与 人 共 同 创 建 了 Zabersoft 公 司 , 该 公 司 在 洛 杉 矶 和 丹 麦 的 Odense 都 设 有 办 事 处 。他 喜 欢 玩 游 戏 。 爱 玩 的 游 戏 有 pinball, bike riding, 偶 尔 还 玩 PS, Dreamcasth 和 MAME 游 戏 。 他 因 忘 了 自 己 曾 经 学 过 的 语 言 : 法 语 、 汉 语 、 日 语而 感 到 悲 哀 。

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 企业管理 > 管理学资料

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报