Win32编程:编码约定

如果你刚开始接触 Windows 编程,确实会遇到一些独特的编码风格和约定,这些可能会让你感到困惑。不过,一旦你熟悉了这些约定,它们实际上会帮助你更好地理解和使用 Windows API。Windows API 使用了许多自定义的数据类型,这些类型通常是为了提高代码的可移植性和可读性。Win32的命名约定采用匈牙利表示法。

匈牙利表示法

匈牙利表示法由 Charles Simonyi 提出,旨在通过前缀提供变量的 语义信息,即变量的用途或含义,这种表示法的目标是避免在错误的上下文中使用变量。

常见前缀示例:
前缀含义示例变量名说明
i索引(Index)iRow表示行索引。
cb字节大小(Count of Bytes)cbBuffer表示缓冲区的大小(以字节为单位)。
rw行号(Row)rwPosition表示行号。
col列号(Column)colPosition表示列号。
p指针(Pointer)pBuffer表示指向缓冲区的指针。
sz以零结尾的字符串(String)szName表示以 \0 结尾的字符串。
int iRow = 10;          // 行索引
int cbBuffer = 1024;    // 缓冲区大小(字节)
char* pBuffer = nullptr; // 指向缓冲区的指针

系统匈牙利表示法是匈牙利表示法的简化版本,主要关注变量的 类型信息。这种形式在 Windows API 和早期的 C/C++ 代码中非常常见。

前缀类型示例变量名说明
dwDWORD(32 位无符号整数)dwSize表示 32 位无符号整数。
wWORD(16 位无符号整数)wParam表示 16 位无符号整数。
bBOOL(布尔值)bFlag表示布尔值。
sz以零结尾的字符串(String)szName表示以 \0 结尾的字符串。
h句柄(Handle)hWnd表示窗口句柄。
p指针(Pointer)pBuffer表示指针。
lp长指针(Long Pointer)lpCmdLine表示长指针(现代系统中与普通指针相同)。
Typedef

Windows API 自定义数据类型的方式主要是通过 类型定义(typedef)宏定义(macro) 来实现的。 其中许多是在头文件 WinDef.h 中定义的。

typedef 是 C/C++ 中的关键字,用于为现有类型定义一个新的别名。下面是后续学习时将经常遇到的一些数据类型。

整数类型
数据类型大小符号
BYTE8 位无符号
DWORD32 位无符号
INT3232 位有符号
INT6464 位有符号
LONG32 位有符号
LONGLONG64 位有符号
UINT3232 位无符号
UINT6464 位无符号
ULONG32 位无符号
ULONGLONG64 位无符号
WORD16 位无符号

此处列出的类型具有固定大小,32 位和 64 应用程序的大小相同。 例如, DWORD 类型始终为 32 位宽。

布尔类型

BOOL 是 Windows API 中定义的一个数据类型,用于表示布尔值(真或假)。

BOOL 是通过 typedef 定义的整数类型别名,通常是 intlong。它在 Windows 头文件 WinDef.h 中定义如下:

同时头文件 WinDef.h 还定义用于 BOOL 的两个值。

#define FALSE    0 
#define TRUE     1

但是,尽管定义 为 TRUE,但大多数返回 BOOL 类型的函数都可以返回任何非零值来指示布尔值,只有 FALSE(0)明确表示假,而任何非零值(不一定是 TRUE)都表示真。 因此,因此在判断 BOOL 值时,应避免直接与 TRUE 比较,而是检查它是否为 FALSE

正确的方式
// Right way.
if (SomeFunctionThatReturnsBoolean()) 
{ 
    ...
}
​
// or
​
if (SomeFunctionThatReturnsBoolean() != FALSE)
{ 
    ...
}
错误的方式
if (result == TRUE) // Wrong!
{
    ... 
}

BOOL 是整数类型,不能与 C++ 的 bool 互换。这是因为BOOL 可以接受任何整数值,而不仅仅是 TRUE(1)和 FALSE(0),但是bool 只能接受 truefalse。如果将 BOOL 值直接赋值给 bool 变量,可能会导致意外的行为。例如:

BOOL b = 2;  // b 是一个非零值,表示真
bool flag = b;  // flag 会被赋值为 true(1),丢失了原始值(2)

指针类型

在 Windows API 中,指针类型的数据类型命名通常遵循一定的约定,使用前缀 P-LP- 来表示指针类型。

前缀的含义
  • P-:表示指针(Pointer)。

  • LP-:表示长指针(Long Pointer)。这是从 16 位 Windows 时代遗留下来的命名习惯,当时有近指针(near)和远指针(far)的区别。在现代 32 位和 64 位系统中,LP-P- 实际上是等价的,但 LP- 仍然被广泛使用以保持一致性。

示例

LPRECT 是指向 RECT 结构体的指针类型。RECT 是一个描述矩形的结构体,定义如下:

typedef struct tagRECT
{
    LONG    left;
    LONG    top;
    LONG    right;
    LONG    bottom;
} RECT, *PRECT, NEAR *NPRECT, FAR *LPRECT;

此时以下变量声明是等效的:

RECT*  rect;  // 指向 RECT 结构的指针
LPRECT rect;  // 指向 RECT 结构的指针
PRECT  rect;  // 指向 RECT 结构的指针
指针精度类型

在 Windows 编程中,指针精度类型(Pointer-Precision Types)是一组特殊的数据类型,它们的大小始终与指针的大小相同。这意味着:

  • 32 位应用程序中,这些类型是 32 位宽(4 字节)。

  • 64 位应用程序中,这些类型是 64 位宽(8 字节)。

以下是常见的指针精度类型及其定义:

类型描述
DWORD_PTR无符号指针精度整数,用于表示指针大小的无符号整数。
INT_PTR有符号指针精度整数,用于表示指针大小的有符号整数。
LONG_PTR有符号指针精度整数,通常用于与 LONG 相关的指针运算。
ULONG_PTR无符号指针精度整数,通常用于与 ULONG 相关的指针运算。
UINT_PTR无符号指针精度整数,通常用于与 UINT 相关的指针运算。

这些类型在 Windows 头文件(如 basetsd.h)中定义,通常是通过 typedef 实现的。相关源代码如下:

用途

①当需要将整数类型转换为指针类型时,使用指针精度类型可以避免精度丢失。

INT_PTR intPtr = 0x12345678;
void* pointer = reinterpret_cast<void*>(intPtr);  // 将整数转换为指针

reinterpret_cast 用于在不相关的类型之间进行转换,例如将整数转换为指针,或将指针转换为整数

②指针运算在内存缓冲区中进行偏移操作

BYTE* buffer = (BYTE*)malloc(100);  // 分配 100 字节的缓冲区
UINT_PTR offset = 50;               // 偏移量
BYTE* newPointer = buffer + offset; // 指针运算
  • UINT_PTR 是一个指针精度的无符号整数类型,其大小与指针相同(32 位平台上为 32 位,64 位平台上为 64 位)。

  • buffer + offset 表示从 buffer 指向的内存地址开始,向后偏移 offset 个字节。

注意

C++ 核心准则(C++ Core Guidelines)建议避免使用匈牙利表示法(或其他类型编码的前缀表示法)Windows 团队在内部已经不再使用匈牙利表示法,但在示例和文档中仍然保留了它的用法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值