C语言handle类型是什么?如何定义与使用?

99ANYc3cd6
预计阅读时长 16 分钟
位置: 首页 C语言 正文

什么是 HANDLE

HANDLE 在 C 语言中不是一个内置的数据类型(如 intchar),而是一个 “句柄”(Handle)

c语言 handle 类型
(图片来源网络,侵删)

你可以把它想象成一个“抽象的钥匙”或者“门票”

  • 钥匙:操作系统管理着大量的资源,比如文件、窗口、内存块、线程、管道等,当你需要使用这些资源时,操作系统不会直接把资源本身(比如文件的全部内容)给你,而是给你一把“钥匙”,也就是一个 HANDLE
  • 门票:你去游乐园,不会把整个游乐园都给你,而是给你一张门票,这张门票(HANDLE)能让你进入特定的项目(资源),但门票本身不是那个项目。

这个“钥匙”或“门票”实际上就是一个*无符号整数值(`void指针或unsigned long`)**,它对程序员来说是一个不透明的黑盒子,你不需要关心它内部具体是什么数值,你只需要把它传递给操作系统提供的特定函数,操作系统就能通过这个值识别出你想要操作的具体资源。


HANDLE 的来源和定义

HANDLE 类型并不是 C 语言标准库的一部分,它来自于 Windows API (Application Programming Interface),当你使用 Windows 提供的头文件(如 windows.h)时,HANDLE 就会被定义。

在 Windows SDK 中,HANDLE 通常被定义为一个指向未知结构的指针,即 void*,使用 void* 可以确保它的通用性,可以代表任何类型的资源。

c语言 handle 类型
(图片来源网络,侵删)
// 在 windows.h 中的典型定义
#ifdef _WIN64
    typedef_PTR(ULONG_PTR) HANDLE; // 在64位系统上是 ULONG_PTR (一个64位无符号整数)
#else
    typedef_PTR(ULONG) HANDLE;    // 在32位系统上是 ULONG (一个32位无符号整数)
#endif

(注意:实际定义可能更复杂,但核心思想就是它是一个指向未知类型的指针或一个无符号整数,其具体大小取决于系统架构。)


HANDLE 的主要特点

  1. 不透明性:这是 HANDLE 最重要的特性,你无法通过 HANDLE 的值直接了解它所代表的资源信息,你不能把它当作普通的整数进行数学运算,也不能直接解引用它,你只能将它作为参数传递给特定的 Windows API 函数。
  2. 通用性:一个 HANDLE 可以代表多种不同类型的 Windows 对象,
    • 文件
    • 窗口
    • 互斥体
    • 事件
    • 线程
    • 进程
    • 动态链接库
    • 等等...
  3. 作用域HANDLE 的生命周期与它所代表的 Windows 资源的生命周期绑定,当你使用完一个资源后,必须调用特定的函数(如 CloseHandle)来“释放”这个句柄,从而通知操作系统可以回收对应的资源,如果忘记关闭,会导致资源泄漏

HANDLE 的常见用法示例

下面通过几个例子来理解 HANDLE 的使用。

示例1:文件操作

当你打开一个文件时,CreateFile 函数会返回一个 HANDLE,后续所有对该文件的操作(如读取、写入、关闭)都通过这个 HANDLE 来完成。

#include <windows.h>
#include <stdio.h>
int main() {
    // 1. 调用 CreateFile 函数,请求操作系统打开一个文件
    //    如果成功,它会返回一个代表该文件的 HANDLE
    HANDLE hFile = CreateFile(
        L"test.txt",                // 文件名
        GENERIC_READ,              // 读取权限
        0,                         // 不共享
        NULL,                      // 默认安全属性
        OPEN_ALWAYS,               // 如果文件不存在则创建
        FILE_ATTRIBUTE_NORMAL,     // 普通文件
        NULL                       // 不使用模板文件
    );
    // 2. 检查 HANDLE 是否有效 (INVALID_HANDLE_VALUE 是一个预定义的无效值)
    if (hFile == INVALID_HANDLE_VALUE) {
        printf("无法打开文件,错误代码: %d\n", GetLastError());
        return 1;
    }
    printf("文件打开成功!句柄值为: %p\n", hFile); // %p 用于打印指针/句柄
    // 3. 使用这个句柄进行其他操作,例如读取文件
    char buffer[256];
    DWORD bytesRead;
    if (ReadFile(hFile, buffer, sizeof(buffer) - 1, &bytesRead, NULL)) {
        buffer[bytesRead] = '\0'; // 确保字符串以 null 
        printf("文件内容: %s\n", buffer);
    }
    // 4. 使用完毕,必须关闭句柄,释放系统资源
    if (!CloseHandle(hFile)) {
        printf("关闭文件句柄失败,错误代码: %d\n", GetLastError());
    }
    return 0;
}

示例2:创建窗口

在 Windows GUI 编程中,创建窗口后,你会得到一个 HWND (Window Handle),它本质上也是一种 HANDLE

c语言 handle 类型
(图片来源网络,侵删)
#include <windows.h>
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
    // ... (注册窗口类的代码省略) ...
    // 1. 创建窗口,返回一个 HWND (本质是 HANDLE)
    HWND hwnd = CreateWindow(
        L"MainWindowClass", L"我的窗口", WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT, 800, 600,
        NULL, NULL, hInstance, NULL
    );
    if (hwnd == NULL) {
        return 1;
    }
    // 2. 显示和更新窗口
    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);
    // ... (消息循环代码省略) ...
    // 3. 程序结束时,销毁窗口
    DestroyWindow(hwnd);
    return 0;
}

与 C++ 的 std::handle 的区别

需要注意的是,C++20 标准库中引入了一个新的 std::handle 类型,它和 Windows API 的 HANDLE完全不同的概念。

  • Windows HANDLE:

    • 是一个平台特定的、与操作系统紧密绑定的概念。
    • 用于管理操作系统资源(文件、窗口等)。
    • 是 C 语言风格的设计,不透明,通过函数指针进行操作。
  • C++ std::handle:

    • 是一个标准库提供的、与操作系统无关的概念。
    • 主要用于管理文件描述符,这是 POSIX 系统(如 Linux, macOS)上的文件 I/O 机制。
    • 是 C++ 风格的设计,旨在提供一个更现代、更安全的句柄抽象,通常与 std::unique_resource 等 RAII (Resource Acquisition Is Initialization) 工具结合使用,以确保资源自动释放。

如果你正在编写 Windows 应用程序,你使用的是 Windows API 的 HANDLE,如果你在 Linux/macOS 上用 C++ 进行跨平台开发,可能会用到 C++ 标准库的 std::handle,两者不能混用。


特性 描述
本质 不是 C 语言内置类型,而是 Windows API 定义的句柄,通常是一个 void* 或无符号整数。
作用 作为一把“钥匙”,让程序员能够间接地操作由操作系统管理的各种资源(文件、窗口、线程等)。
关键原则 不透明性:不要尝试解释或修改其内部值,只将它作为参数传递给特定的 API 函数。
生命周期 必须手动管理,使用完资源后,必须调用 CloseHandle(或类似函数)来释放,否则会造成资源泄漏。
通用性 一个 HANDLE 可以代表多种不同类型的 Windows 对象,是 Windows 编程中的核心概念。

理解 HANDLE 是掌握 Windows 系统级编程的关键一步,它代表了操作系统与用户程序之间的一种契约,保证了系统资源的安全和有效管理。

-- 展开阅读全文 --
头像
C语言函数调用如何正确使用?
« 上一篇 02-26
union date结构如何正确使用与内存布局?
下一篇 » 02-26

相关文章

取消
微信二维码
支付宝二维码

目录[+]