不行,_fileno不是标准C++函数,仅MSVC/MinGW等部分环境支持,且需流已打开、绑定真实文件、使用binary模式,并先获取FILE(但C++标准不暴露FILE),跨平台不可靠。
用
从 C++
拿到 C 文件描述符,行不行?
行,但必须确保流底层绑定的是真实文件(非内存、管道、重定向等),且已打开、未缓冲失败。
是 MSVC 和部分 POSIX 兼容环境(如 MinGW)提供的扩展函数,
不是标准 C++
,GCC/Clang 在纯 Linux 下默认不提供,会报
。
常见错误现象:
—— 因为
内部 FILE* 可能未初始化或已被关闭。
只对
/
/
有效,且必须用
模式打开(文本模式下换行处理可能干扰底层 fd 一致性)
调用前务必检查流状态:
MSVC 中需包含
;MinGW 需链接
或启用
C++ 流怎么拿到对应的
?这是
的前提
输入是
,不是 C++ 流对象。C++ 标准库不暴露
,但各实现有私有接口:MSVC 提供
(仅 debug 版可用),lib
c++
和 libstdc++ 均不公开该能力。所以「先取
再调
」这条路在跨平台项目里基本走不通。
实际能稳定用的路径只有一条:绕过 C++ 流,用 C 打开文件,再用
构造 C++ 流 —— 反向操作更可靠。
立即学习
“
C++免费学习笔记(深入)
”;
C知道
CSDN推出的一款AI技术问答工具
下载
正确姿势:
不要试图从
、
或重定向后的流取 fd —— 它们的
可能被封装、复用或根本不存在(如 libc++ 用自研 buffer)
是 GNU libstdc++ 的扩展(非标准),返回 int,但仅当用
绑定过 fd 后才有效;直接构造的流返回 -1
Linux/macOS 下替代
的可移植方案
别硬啃
。POSIX 系统上,所有 I/O 最终都落到 fd,关键是怎么让 C++ 流和 fd 对齐。标准做法是:用
/
等系统调用拿到 fd,再用
包装成
,最后用
的非标准构造函数(libstdc++ 支持)或自己继承
转接。
示例(libstdc++ 环境):
真正跨平台的做法是:放弃混合使用,同一模块统一用 C 文件 I/O(
/
)或统一用 C++ 流(
/
),中间不转换
若必须桥接(如调第三方 C 库需要 fd),优先用
复制一份,避免 C++ 流析构时误关原始 fd
注意缓冲区同步:
和
不互通,混用极易丢数据
为什么你看到的「附源码」示例总在 Windows 上跑通?
因为 MSVC 的
内部确实持有一个
,且
就是直接读那个字段 —— 这属于实现细节泄漏。换个编译器、升个 libc++ 版本、甚至加个
,就可能因内联优化导致
返回空指针。
测试时别只看是否编译通过,要验证 fd 是否真能
/
—— 很多“成功”只是返回了某个无效值(如 3,其实是 stderr 的 fd)
CI 环境(尤其是 Linux + Clang)大概率挂掉,别信本地 Windows 测试结果
最隐蔽的坑:
—— 这种野指针访问在 ASan 下立刻崩溃
真要拿 fd,就老实用
;真要用 C++ 流,就别动它的底层。两者硬凑,边界模糊的地方比代码还多。
_filenostd::fstream_filenoundefined reference to `_fileno'std::ofstream f("out.txt"); int fd = _fileno(f); // fd == -1 或崩溃fstd::fstreamstd::ifstreamstd::ofstreamstd::ios_base::binaryif (f.is_open() && f.rdbuf() != nullptr)-lmsvcrt-D__USE_MINGW_ANSI_STDIOFILE*_fileno_filenoFILE*FILE*_get_stream_handle()FILE*_filenofdopenint fd = open("data.bin", O_RDWR | O_CREAT, 0644); std::filebuf fb; fb.attach(fd); std::iostream fs(&fb);std::coutstd::cinFILE*std::filebuf::fd()attach()_fileno_filenoopen()socket()fdopen()FILE*std::filebufstd::streambufint fd = open("log.txt", O_WRONLY | O_APPEND | O_CREAT, 0644);
FILE* fp = fdopen(fd, "a");
std::filebuf fb;
fb.pubsetbuf(nullptr, 0);
fb.open("/dev/null", std::ios_base::out); // 占位
// 实际需反射调用 _M_file设为fp(不推荐)→ 更稳妥:直接用 fp + fprintffreadfwritereadwritedup(fd)fflush(fp)fs.flush()std::filebufFILE*_fileno-O2rdbuf()read()write()std::ofstream f("x.txt", std::ios::app); int fd = _fileno(f.rdbuf()->_IO_file_flags ? ...)open()