最推荐用 std::vector 配合 std::ifstream:先 seekg 到末尾获取长度,resize 后 read 到 data(),自动管理内存且安全;若必须裸指针,优先用 std::make_unique(size)。

用 fopen + fread 读取文件到指针指向的内存
直接用指针读文件,本质是先分配内存,再把文件内容“倒”进去。C++里没强制要求用 C 风格 I/O,但若你明确想用指针操作(比如对接 C API、做内存映射前准备),fopen + fread 是最轻量、最可控的方式。
常见错误是忘记检查返回值,或把 fread 的返回值当成字节数误用——它返回的是成功读取的“元素个数”,不是字节数,除非你设元素大小为 1。
- 先用
fseek(fp, 0, SEEK_END)定位到末尾,再ftell(fp)获取文件长度,然后malloc分配等长内存 - 回到开头:
fseek(fp, 0, SEEK_SET),再调用fread(buf, 1, size, fp),第二个参数写1,第三个参数写实际字节数,才能保证读满 - 读完必须
fclose(fp);malloc的内存记得free(buf),否则泄漏 - 如果文件为空,
ftell返回 0,malloc(0)行为未定义(多数实现返回 nullptr 或非法地址),需单独判断
std::ifstream 配合 std::vector<char></char> 模拟“指针读取”
现代 C++ 更推荐用 std::ifstream,但它默认不暴露裸指针。你可以让它读进 std::vector<char></char>,再用 &vec[0] 或 vec.data() 获取有效指针——这比手管 malloc 安全得多,且自动管理生命周期。
注意:空 vector 的 data() 是 nullptr,访问前必须确认 vec.size() > 0;&vec[0] 在空时会崩溃,绝对不能用。
- 打开文件时加
std::ios::binary标志,否则 Windows 下换行符可能被误转,导致长度不准 - 用
file.seekg(0, std::ios::end)然后file.tellg()获取长度,再vec.resize(size) - 再
file.seekg(0, std::ios::beg),调用file.read(vec.data(), size)—— 这里read是按字节写的,语义清晰 -
file.gcount()返回实际读取字节数,可能小于size(比如磁盘错误或权限不足),必须检查
为什么不该用 new char[n] + read 手动管理?
有人习惯写 char* buf = new char[size]; file.read(buf, size);,看起来简洁,但隐患多。
最大问题是异常不安全:如果 file.read() 前发生异常(比如构造 std::ifstream 失败),buf 就泄漏了;就算没异常,忘了 delete[] buf 也是常见 bug。
-
std::vector<char></char>在栈上构造,析构自动释放,无泄漏风险 -
std::unique_ptr<char></char>也可用,但需手动reset()和尺寸记录,不如 vector 直观 - 如果真要用裸指针(如对接 legacy C 函数),优先选
std::make_unique<char>(size)</char>,它支持数组 delete,且移动安全
读大文件时指针操作的边界陷阱
文件大小超过 2GB 时,ftell 和 tellg() 在 32 位系统或某些旧编译器下会截断——返回 long,而大文件偏移需要 off_t 或 std::streamoff。
更隐蔽的问题是:malloc 或 new 可能失败,但错误不抛异常(new 默认抛 std::bad_alloc,malloc 返回 nullptr)。一旦忽略,后续 fread 或 read 写入空指针,直接 crash。
- 用
std::ifstream::tellg()前,确保流状态良好:if (!file) return; - 分配内存后,立刻检查指针是否为 nullptr(
malloc)或捕获std::bad_alloc(new) - 对超大文件,考虑分块读取,避免单次分配过大内存;此时“指针”应理解为每次指向当前块起始,而非整个文件
实际项目里,真正需要裸指针读文件的场景不多。多数时候,用 std::vector<char></char> 拿到 data() 就够了——它既满足指针访问需求,又避开手动内存管理的所有坑。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











