c++ 控制台常用句柄(STD_INPUT_HANDLE、STD_OUTPUT_HANDLE、STD_ERROR_HANDLE)

前言

我最近发过很多的控制台的代码
有很多次要用到什么句柄什么STD_INPUT_HANDLESTD_OUTPUT_HANDLESTD_ERROR_HANDLE都是塞在GetStdHandle函数里的
正片开始


输入句柄STD_INPUT_HANDLE

在默认情况下,标准输入设备通常是键盘,用于接收用户输入的字符或命令1
通过获取这个句柄,开发者可以读取用户的输入,或者更改输入设备的模式,如禁用或启用特定的输入处理(如鼠标输入、快速编辑模式等)。

输出句柄STD_OUTPUT_HANDLE

在默认情况下,标准输出设备通常是控制台窗口,用于显示文本信息。
通过获取这个句柄,开发者可以使用 Windows API 函数来更改控制台的输出属性、位置、文本颜色等,或者将输出重定向到文件或其他设备。

错误句柄STD_ERROR_HANDLE

STD_ERROR_HANDLE通常用于将错误信息输出到标准错误设备,这通常是控制台窗口,但也可以被重定向到文件或其他设备。与标准输出不同,标准错误输出通常用于显示程序运行时的错误或警告信息,以便用户能够区分正常输出和错误信息。

前人踩过的坑(迷惑代码,请勿模仿)

我才不会告诉你是我踩的坑
我想要搞一个控制不能用Ctrl+C和选择模式的代
并且输出 ---\n:

#include <iostream>
using namespace std;
#include <windows.h>  
#include "console.h"

int main(){
	HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
	DWORD mode;
    GetConsoleMode(hConsole, &mode);
    
    // 禁用鼠标输入模式  
	SetConsoleMode(hConsole, mode & ~(ENABLE_PROCESSED_INPUT|ENABLE_QUICK_EDIT_MODE));
	printf(" ----\n");
	system("pause>nul");
    return 0;  
}

可是。。。
换行?
这个空心的是。。。换行?!!!
怎么办?!!!
再一看。。。
GetStdHandle(STD_OUTPUT_HANDLE) 错了!!!
STD_INPUT_HANDLE!!!
正确的代码

#include <iostream>
using namespace std;
#include <windows.h>  
#include "console.h"

int main(){
	HANDLE hConsole = GetStdHandle(STD_INPUT_HANDLE);
	DWORD mode;
    GetConsoleMode(hConsole, &mode);
    
    // 禁用鼠标输入模式  
	SetConsoleMode(hConsole, mode & ~(ENABLE_PROCESSED_INPUT|ENABLE_QUICK_EDIT_MODE));
	printf(" ----\n");
	system("pause>nul");
    return 0;  
}

  1. 接收用户输入的字符或命令:这里可以看我的文章c++ GetAsyncKeyState实时监看控制台事件c++ 实时监看控制台事件(ReadConsoleInput的运用) ↩︎

<think>好的,我需要解决用户关于`#defineSTD_OUTPUT_HANDLE((DWORD)-11)`的定义和使用问题。首先,用户之前的问题已经涉及了这个宏的作用、API函数、代码示例和注意事项,现在用户可能想更深入了解其底层机制或常见问题。用户提供的引用内容中,引用[3]提到了文件句柄的操作,比如`usb_handle`和`fd`的处理,这可能与标准输出句柄的管理有相似之处。虽然引用中的内容涉及ADB和USB,但可以联想到WindowsAPI中句柄的使用方式,比如打开、读写和关闭。这可能帮助解释`STD_OUTPUT_HANDLE`如何被系统内部管理,比如如何通过句柄进行I/O操作,或者错误处理。接下来,我需要确认用户可能关心的问题点。例如,为什么使用负数作为句柄标识?DWORD是32位无符号整数,-11转换为十六进制是0xFFFFFFF5,这在WindowsAPI中是否常见?此外,用户可能遇到获取句柄失败的情况,如何处理INVALID_HANDLE_VALUE?或者,当使用WriteConsole时出现编码问题? 另外,结合引用[1]提到的RTTI异常,虽然主要针对C++的Windows代码,但可能与类型转换相关,比如将HANDLE类型转换为其他类型时需要注意的问题。例如,HANDLE本质是void指针,但标准句柄STD_OUTPUT_HANDLE是预定义的常量,这可能涉及到类型安全的问题。 引用[2]提到了权限降级,这可能与安全相关,比如在获取高权限句柄时是否需要调整权限,但标准输出句柄通常不需要,不过如果用户程序以管理员权限运行时,是否会影响控制台输出?这可能需要进一步探讨。现在,我需要组织回答结构,确保涵盖定义、数值解释、常见使用问题及解决方案。同时,引用相关部分来支持解释,比如引用[3]中的句柄操作流程,可以类比说明标准输出句柄的使用步骤。此外,用户可能对如何调试句柄错误感兴趣,比如使用GetLastError()获取错误代码,并处理错误情况。最后,生成的相关问题需要与主题紧密相关,比如如何获取其他标准句柄句柄无效的原因、跨平台兼容性问题等。确保这些问题能够引导用户进一步深入学习。</think>### `#define STD_OUTPUT_HANDLE ((DWORD)-11)` 的定义与使用详解 #### 1. **数值定义分析** `STD_OUTPUT_HANDLE` 的定义为 `(DWORD)-11`,其本质是: - **DWORD 类型**:32位无符号整数,因此 `-11` 会被转换为补码形式,即 `0xFFFFFFF5`[^1] - **系统预定义句柄标识**:Windows 使用负数标识标准设备,如: - `STD_INPUT_HANDLE` (`-10`) - `STD_ERROR_HANDLE` (`-12`) #### 2. **句柄使用核心问题** ##### (1) 句柄获取失败 调用 `GetStdHandle(STD_OUTPUT_HANDLE)` 可能返回 `INVALID_HANDLE_VALUE`(值为 `0xFFFFFFFF`),常见原因: - **未绑定控制台**:非控制台程序(如 GUI 应用)默认无标准输出句柄 - **重定向冲突**:若输出被重定向到文件,可能无法获取原始控制台句柄[^3] **解决方案**: ```c HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE); if (hOut == INVALID_HANDLE_VALUE) { DWORD err = GetLastError(); // 处理错误,如通过AllocConsole()创建新控制台 } ``` ##### (2) 多线程同步问题 多线程同时操作同一输出句柄可能导致输出混乱: ```c // 错误示例:未加锁的并发写入 WriteConsole(hOut, "Thread1\n", 8, NULL, NULL); WriteConsole(hOut, "Thread2\n", 8, NULL, NULL); ``` **解决方案**:使用临界区(Critical Section)或互斥量(Mutex)同步操作。 #### 3. **编码与字符集问题** `WriteConsole()` 默认使用 UTF-16 LE 编码,若需输出 ANSI 字符需转换: ```c char* ansiText = "ANSI Text"; WCHAR wideText[256]; MultiByteToWideChar(CP_ACP, 0, ansiText, -1, wideText, 256); WriteConsoleW(hOut, wideText, wcslen(wideText), NULL, NULL); ``` #### 4. **跨平台兼容性** 在非 Windows 系统(如 Linux)中,标准输出通过文件描述符(如 `STDOUT_FILENO=1`)实现。跨平台代码需使用条件编译: ```c #ifdef _WIN32 HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE); #else int fdOut = STDOUT_FILENO; #endif ``` #### 5. **调试技巧** - **检查句柄有效性**:使用 `GetFileType(hOut)`,若返回 `FILE_TYPE_UNKNOWN` 则表示句柄无效 - **输出重定向检测**:通过 `GetConsoleMode(hOut, &mode)` 检测是否关联到真实控制台 --- ### 代码示例:安全的控制台输出 ```c #include <windows.h> #include <stdio.h> int main() { HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE); if (hOut == INVALID_HANDLE_VALUE) { if (!AllocConsole()) { // 尝试创建新控制台 fprintf(stderr, "Error: %lu\n", GetLastError()); return 1; } hOut = GetStdHandle(STD_OUTPUT_HANDLE); } // 设置输出颜色为绿色 SetConsoleTextAttribute(hOut, FOREGROUND_GREEN); DWORD written; const char* text = "Secure console output\n"; WriteConsoleA(hOut, text, strlen(text), &written, NULL); return 0; } ``` ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值