核心要点
getline是一个 POSIX 标准:它不是标准 C 库(如stdio.h)的一部分,而是 POSIX.1-2008 标准中定义的,这意味着它在 Linux、macOS 和其他类 Unix 系统上可用,但在 Windows 的标准 C 库中默认不可用(需要额外配置,如使用 MinGW 或 Cygwin)。getline会自动分配内存:这是它与fgets最大的不同,你不需要预先定义一个固定大小的字符数组来存储输入。getline会根据输入的长度动态地分配足够的内存。- **你必须手动释放内存:因为
getline动态分配了内存,所以当这个内存不再需要时,你必须使用free()函数将其释放,否则会导致内存泄漏。
getline 函数原型
#include <stdio.h> #include <stdlib.h> // 用于 free() ssize_t getline(char **lineptr, size_t *n, FILE *stream);
参数详解:
-
char **lineptr(指向字符指针的指针)
(图片来源网络,侵删)- 这是一个“双重指针”,它指向一个字符指针。
- 第一次调用时:你可以将它设为
NULL。getline会为你分配内存,并将新分配的内存地址存入*lineptr。 - 后续调用时:
lineptr应该指向上一次调用getline时返回的内存地址。getline会检查这块空间是否足够,如果不够,它会重新分配更大的内存,并更新*lineptr中的地址。
-
size_t *n(指向 size_t 的指针)- 这是一个指向“缓冲区大小”的指针。
- 第一次调用时:你可以将它设为
NULL。getline会分配内存,并将分配的大小存入*n。 - 后续调用时:
n应该指向上一次调用getline时返回的大小。getline会用它来判断是否需要重新分配内存。
-
FILE *stream(文件流指针)- 你想从哪里读取输入,通常是
stdin(标准输入,即键盘),也可以是一个文件指针(如fopen返回的指针)。
- 你想从哪里读取输入,通常是
返回值:
- 成功时:返回读取的字符数(包括换行符
\n),如果读取到文件末尾则返回 -1。 - 失败时:返回 -1(内存分配失败或发生 I/O 错误)。
free 函数原型
#include <stdlib.h> void free(void *ptr);
- 作用:释放一个由
malloc、calloc、realloc或getline等函数动态分配的内存块。 - 参数:
ptr是一个指向要释放的内存块起始地址的指针。 - 重要:释放内存后,最好将指针设为
NULL,以防止“悬垂指针”(dangling pointer),即指针仍然指向一个已释放的内存地址,使用这个指针会导致未定义行为。
完整示例代码
下面是一个完整的、可运行的示例,演示了如何使用 getline 读取用户输入的每一行,并在处理完后释放内存。
#include <stdio.h>
#include <stdlib.h> // 包含 getline 和 free 的头文件
int main() {
char *line = NULL; // 初始化为 NULL,让 getline 来分配内存
size_t len = 0; // 初始化为 0,让 getline 来决定大小
ssize_t read;
printf("请输入多行文本,按 Ctrl+D (Linux/macOS) 或 Ctrl+Z (Windows) 结束输入:\n");
// 循环读取每一行,直到 getline 返回 -1 (EOF)
while ((read = getline(&line, &len, stdin)) != -1) {
// getline 会读取换行符,所以我们用 printf 来打印它
printf("你输入了: %s", line);
// 你可以对 line 指向的字符串进行处理...
// 解析、修改、写入文件等
}
// --- 关键步骤:释放内存 ---
// 当循环结束后,line 指向的内存不再需要了
if (line) {
free(line);
line = NULL; // 养成好习惯,将指针置为 NULL
}
printf("\n输入结束,内存已释放,\n");
return 0;
}
如何编译和运行 (在 Linux/macOS 上):
- 将代码保存为
getlinetest.c。 - 打开终端,使用
gcc进行编译:gcc getlinetest.c -o getlinetest
- 运行生成的可执行文件:
./getlinetest
示例交互:
请输入多行文本,按 Ctrl+D (Linux/macOS) 或 Ctrl+Z (Windows) 结束输入:
Hello, World!
你输入了: Hello, World!
This is a test for getline.
你输入了: This is a test for getline.
Another line.
你输入了: Another line.
输入结束,内存已释放。
常见问题与最佳实践
为什么必须 free?
getline 使用了 malloc 或 realloc 在堆上分配内存,与栈上的内存(如 char buffer[256];)不同,堆上的内存不会在函数结束时自动释放,它会一直存在,直到你的程序显式地调用 free 来释放它,如果在一个循环中反复调用 getline 而不 free,程序的内存占用会无限增长,最终耗尽系统内存,导致程序崩溃。

(图片来源网络,侵删)
getline vs. fgets
| 特性 | getline |
fgets |
|---|---|---|
| 内存管理 | 自动分配,非常灵活 | 需要预先分配,有固定大小限制 |
| 缓冲区大小 | 动态调整 | 固定,由你定义(如 char line[256];) |
| 安全性 | 高,不会溢出 | 低,如果输入超过缓冲区大小,会导致缓冲区溢出,这是严重的安全漏洞 |
| 标准 | POSIX 标准,非标准 C | 标准 C 库 (stdio.h) |
| 跨平台性 | 较差 (Windows 需额外配置) | 非常好,所有平台都支持 |
只要条件允许(尤其是在 Linux/Unix 环境下),getline 是处理用户输入或文件行的更安全、更方便的选择。
在 Windows 上使用 getline
如果你在 Windows 上(例如使用 Visual Studio),getline 默认不可用,你有两个选择:
- 使用 MinGW/Cygwin:安装 MinGW 或 Cygwin,它们提供了类 Unix 环境,其中包含了
getline函数。 - 自己实现或寻找替代品:你可以自己写一个简单的读取一行函数,或者使用 C++ 的
std::getline(如果你允许使用 C++),对于纯 C 环境,一个常见的替代方案是结合fgets和realloc来模拟getline的行为,但这会增加代码复杂度。

(图片来源网络,侵删)
