Win32:字符串的使用

在 Windows 操作系统中,Unicode 是首选的字符编码方式,因为它能够支持全球范围内的所有字符集和语言。Windows 使用 UTF-16 编码【通常被称为“宽字符”(wide characters)】来表示 Unicode 字符。UTF-16 是一种变长编码,每个字符可以编码为一个或两个 16 位的值(即一个或两个 wchar_t 类型的数据)。

数据类型和定义

为了在 Windows 编程中更方便地使用宽字符,Windows SDK 提供了一些相关的数据类型和定义。头文件 WinNT.h 还定义了以下 typedef

typedef wchar_t WCHAR;

若要声明宽字符文本或宽字符字符串字面量,请将 L 置于文本前面。

wchar_t a = L'a';
wchar_t *str = L"hello";

通过以下例子查看加L和不加L的区别:

#include <iostream>
#include <windows.h>
​
#pragma comment( linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"" ) // 设置入口地址
int main() {
    MessageBoxA(NULL,"Hello Wolven","Hey",MB_OK);
    MessageBoxW(NULL, L"Hello World", L"Hello", MB_OK);
​
    system("pause");
}

在反汇编界面查看字符串地址。

对比:

不加L字符串每个字符占一字节,加上L的字符串一个字符占两个字节。

Unicode 和 ANSI 函数

Microsoft 在引入 Unicode 支持时,为了兼容现有的 ANSI 代码和逐步过渡到 Unicode,提供了两套并行的 API:一套用于 ANSI 字符串(8 位字符),另一套用于 Unicode 字符串(UTF-16 编码的宽字符)。这种设计使得开发者可以根据需要选择使用 ANSI 或 Unicode 版本。

例如,有两个函数可以设置窗口标题栏的文本:

  • SetWindowTextA 采用 ANSI 字符串。

  • SetWindowTextW 采用 Unicode 字符串。

在内部,ANSI 版本将字符串转换为 Unicode。 Windows 标头还定义了一个宏,该宏在定义预处理器符号 UNICODE 或 ANSI 版本时解析为 Unicode 版本。

#ifdef UNICODE
#define SetWindowText  SetWindowTextW
#else
#define SetWindowText  SetWindowTextA
#endif

新应用程序应始终调用 Unicode 版本。 许多世界语言都需要 Unicode。 如果使用 ANSI 字符串,则不可能对应用程序进行本地化。 ANSI 版本的效率也较低,因为操作系统必须在运行时将 ANSI 字符串转换为 Unicode。 根据偏好,可以显式调用 Unicode 函数,例如 SetWindowTextW 或使用宏。 最新的 Windows API 通常只有 Unicode 版本。

Visual Studio 中如何设置项目的字符集
右击项目->选择属性

项目属性页->常规->项目默认值->字符集

在右侧的 字符集 选项中,可以选择:

  • 使用 Unicode 字符集:启用 Unicode 支持(推荐)。

  • 使用多字节字符集:使用 ANSI 字符集。

  • 未设置:默认行为,通常取决于编译器设置。

Windows SDK 提供的通用机制

除此之外Windows SDK提供了一些通用的宏和数据类型,使得开发者可以编写与字符集无关的代码。这些宏和数据类型会根据目标平台的字符集设置(ANSI 或 Unicode),自动将字符串映射到正确的类型(charwchar_t)。这样,同一份代码可以在不同的字符集设置下编译,而无需修改代码。

为什么需要这种机制?

为了支持ANSI 和 Unicode两种字符集,Windows API 提供了两套函数,例如:

  • SetWindowTextA:接受 ANSI 字符串。

  • SetWindowTextW:接受 Unicode 字符串。

如果直接使用 SetWindowTextASetWindowTextW,代码会与特定的字符集绑定,无法灵活切换。为了避免这个问题,Windows SDK 提供了一些宏和数据类型,使得代码可以根据编译时的字符集设置自动选择正确的版本。

UnicodeANSI
TCHARwchar_tchar
TEXT("x")_T("x")L"x""x"

1. 通用字符类型 TCHAR

TCHAR 是一个通用的字符类型,它的定义如下:

#ifdef UNICODE
    typedef wchar_t TCHAR;
#else
    typedef char TCHAR;
#endif
  • 如果定义了 UNICODE 宏,TCHARwchar_t

  • 如果没有定义 UNICODE 宏,TCHARchar

2. 通用字符串宏 TEXT

TEXT 是一个通用的字符串宏,用于定义字符串字面量。

#ifdef UNICODE
    #define TEXT(quote) L##quote
#else
    #define TEXT(quote) quote
#endif
  • 如果定义了 UNICODE 宏,TEXT("Hello") 会被解析为 L"Hello"(宽字符字符串)。

  • 如果没有定义 UNICODE 宏,TEXT("Hello") 会被解析为 "Hello"(ANSI 字符串)。

例如,以下代码:

SetWindowText(TEXT("My Application"));

解析为下列之一:

SetWindowTextW(L"My Application"); // 宽字符字符串
​
SetWindowTextA("My Application");  // ANSI字符串
总结

Windows SDK 提供的通用机制(如 TCHARTEXT 和通用 API 宏)使得开发者可以编写与字符集无关的代码。通过定义或取消定义 UNICODE 宏,可以灵活地切换字符集模式,从而支持 ANSI 或 Unicode 字符串。这种机制提高了代码的可移植性和可维护性,是现代 Windows 编程的推荐做法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值