当前位置:首页 > 技术 > 正文内容

C++中的char与TCHAR:理解窄字符与宽字符

访客 技术 2026年7月30日 1

在C++开发中,处理字符串类型时,常常会遇到charTCHAR(窄字符与宽字符)的概念。这与C#中的string类型存在差异,需要深入理解。

字符集基础

在深入探讨charTCHAR之前,了解不同的字符集至关重要:

  • ANSI: 这是一个8位编码,最多能表示256个字符。它主要适用于英文环境,对于包含多国语言的系统则显得不足。为了解决这个问题,出现了多字节字符集。
  • UTF-8: 是一种可变长度编码,它使用1到4个字节来表示字符。ASCII字符(小于0x0080)占用1个字节。0x0080到0x07ff范围内的字符占用2个字节。0x0800及以上的字符占用3个字节,特殊字符可能占用4个字节。相比UTF-16,UTF-8在处理大于0x0800的字符时效率稍低。
  • UTF-16: 使用2个字节表示大部分字符。当2个字节不足以表示时,它会使用代理对(surrogate pairs)来编码。Unicode字符集本身就是UTF-16格式。
  • UTF-32: 使用固定的4个字节来编码所有字符,确保了表示能力,但同时也增加了内存占用。

Windows API中的字符转换

在Windows环境下,经常需要在ANSI(多字节)和Unicode(宽字符)之间进行转换。Windows API提供了相应的函数来实现这些转换。

多字节字符转换为宽字符:MultiByteToWideChar

MultiByteToWideChar函数用于将ANSI(多字节)字符串转换为Unicode(宽字符)字符串。

int MultiByteToWideChar(
  UINT uCodePage,           // 指定源字符串的代码页
  DWORD dwFlags,            // 控制转换行为的标志(通常为0)
  LPCSTR lpMultiByteStr,    // 指向要转换的多字节字符串
  int cbMultiByte,          // 多字节字符串的长度(字节数),-1表示自动计算
  LPWSTR lpWideCharStr,     // 指向接收转换后宽字符字符串的缓冲区
  int cchWideChar           // 接收缓冲区的最大字符数
);
  • uCodePage: 定义了输入的多字节字符串所使用的代码页。
  • dwFlags: 控制转换的一些额外行为,例如处理变音符号。通常情况下,此参数设为0。
  • lpMultiByteStr: 指向待转换的C风格字符串。
  • cbMultiByte: 指定lpMultiByteStr的长度(字节)。若设为-1,则函数会自行计算字符串长度。
  • lpWideCharStr: 一个缓冲区指针,用于存储转换后的宽字符字符串。
  • cchWideChar: lpWideCharStr缓冲区的大小(字符数)。

进行转换的典型步骤:

  1. 预估缓冲区大小: 首次调用MultiByteToWideChar,将lpWideCharStr设为NULLcchWideChar设为0,cbMultiByte设为-1。函数将返回所需的宽字符数(包括终止符'\0')。
  2. 分配内存: 根据上一步返回的大小,分配足够存储宽字符字符串的内存。
  3. 实际转换: 再次调用MultiByteToWideChar,这次将分配好的内存地址传给lpWideCharStr,并将第一次调用返回的大小传给cchWideChar
  4. 使用字符串: 使用转换后的宽字符字符串。
  5. 释放内存: 释放之前分配的内存。

宽字符字符串转换为多字节字符:WideCharToMultiByte

WideCharToMultiByte函数用于将Unicode(宽字符)字符串转换为ANSI(多字节)字符串。

int WideCharToMultiByte(
  UINT uCodePage,           // 指定目标字符串的代码页
  DWORD dwFlags,            // 控制转换行为的标志(通常为0)
  LPCWSTR lpWideCharStr,    // 指向要转换的宽字符字符串
  int cchWideChar,          // 宽字符字符串的长度(字符数),-1表示自动计算
  LPSTR lpMultiByteStr,     // 指向接收转换后多字节字符串的缓冲区
  int cbMultiByte,          // 接收缓冲区的最大字节数
  LPCSTR lpDefaultChar,     // 无法转换时使用的默认多字节字符(通常为NULL)
  LPBOOL lpUsedDefaultChar  // 指示是否使用了默认字符(通常为NULL)
);
  • uCodePage: 定义了目标多字节字符串的代码页。
  • dwFlags: 控制转换行为的标志。
  • lpWideCharStr: 指向待转换的宽字符C风格字符串。
  • cchWideChar: lpWideCharStr的长度(字符数)。若设为-1,则函数会自行计算字符串长度。
  • lpMultiByteStr: 一个缓冲区指针,用于存储转换后的多字节字符串。
  • cbMultiByte: lpMultiByteStr缓冲区的大小(字节数)。
  • lpDefaultChar: 当宽字符无法映射到目标代码页时,使用的默认多字节字符。如果为NULL,则使用系统默认字符(通常是'?')。
  • lpUsedDefaultChar: 一个布尔变量指针。如果转换过程中有字符未使用默认字符,则设为TRUE,否则为FALSE。通常设为NULL

需要注意的是,当lpDefaultCharNULL且转换遇到无法映射的字符时,可能会使用问号('?')。在处理文件名等场景时,这可能导致问题,因为问号在文件名中通常是通配符。

返回列表

上一篇:HBase Shell 常用命令速查与实践

没有最新的文章了...

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。