c - 为什么 getline 的第一个参数是指向指针 "char**"而不是 "char*"的指针?

标签 c function gcc

我使用 getline 函数从 STDIN 中读取一行。

getline的原型(prototype)是:

ssize_t getline(char **lineptr, size_t *n, FILE *stream);

我将其用作测试程序,它来自 http://www.crasseux.com/books/ctutorial/getline.html#getline

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int atgc, char *argv[])
{
    int bytes_read = 1;
    int nbytes = 10;
    char *my_string;

    my_string = (char *)malloc(nbytes+1);

    puts("Please enter a line of text");

    bytes_read = getline(&my_string, &nbytes, stdin);

    if (bytes_read == -1)
    {
        puts ("ERROR!");
    }
    else
    {
        puts ("You typed:");
        puts (my_string);
    }

    return 0;
}

这很好用。

我的疑问是?

  1. 为什么使用 char **lineptr 而不是 char *lineptr 作为函数 getline 的参数?

    <
  2. 为什么我用下面的代码会出错:

    char **my_string;
    bytes_read = getline(my_string, &nbytes, stdin); 
    
  3. 我对 *& 感到困惑。

部分警告:

testGetline.c: In function ‘main’: 
testGetline.c:34: warning: pointer targets in passing argument 2 of  
  ‘getline’ differ in signedness 
/usr/include/stdio.h:671: 
  note: expected ‘size_t * __restrict__’ but argument is of type ‘int *’  
testGetline.c:40: warning: passing argument 1 of ‘putchar’ makes integer 
  from pointer without a cast 
/usr/include/stdio.h:582: note: expected ‘int’ but argument is of 
  type ‘char *’

我使用 GCC 版本 4.4.5 (Ubuntu/Linaro 4.4.4-14ubuntu5)。

最佳答案

Why use char **lineptr instead of char *lineptr as a parameter of function getline?

想象一下 getline 的原型(prototype)看起来像这样:

ssize_t
getline(char *line, size_t n, FILE *stream);

你这样调用它:

char *buffer = NULL;
size_t len = 0;
ssize_t read = getline(buffer, len, stdin);

在调用getline之前,buffer为空:

+------+
|buffer+-------> NULL
+------+

getline 被调用时,line 获取 buffer 的副本,因为函数参数在 C 中是按值传递的。 getline 内部,我们无法再访问 buffer:

+------+
|buffer+-------> NULL
+------+          ^
                  |
+------+          |
| line +----------+
+------+

getline 使用 malloc 分配一些内存并将 line 指向 block 的开头:

+------+
|buffer+-------> NULL
+------+

+------+        +---+---+---+---+---+
| line +------->+   |   |   |   |   |
+------+        +---+---+---+---+---+

getline 返回后,我们无法再访问 line:

+------+
|buffer+-------> NULL
+------+

我们又回到了起点。我们不能将 buffer 重新指向 getline 中新分配的内存,因为我们只有 buffer 的副本。


getline的原型(prototype)实际上是:

ssize_t
getline(char **lineptr, size_t *n, FILE *stream);

你这样调用它:

char *buffer = NULL;
size_t len = 0;
ssize_t read = getline(&buffer, &len, stdin);

&buffer 返回指向 buffer 的指针,所以我们有:

+-------+        +------+
|&buffer+------> +buffer+-------> NULL
+-------+        +---+--+

getline 被调用时,lineptr 得到 &buffer 的副本,因为 C 是按值调用的。 lineptr 指向与&buffer 相同的地方:

+-------+        +------+
|&buffer+------->+buffer+-------> NULL
+-------+        +---+--+
                     ^
+-------+            |
|lineptr+------------+
+-------+

getline 使用 malloc 分配一些内存并指向 lineptr 的指针(即 lineptr 指向的东西) 在 block 的开头:

+-------+        +------+        +---+---+---+---+---+
|&buffer+------->+buffer+------->+   |   |   |   |   |
+-------+        +---+--+        +---+---+---+---+---+
                     ^
+-------+            |
|lineptr+------------+
+-------+

getline 返回后,我们无法再访问 lineptr,但我们仍然可以通过 buffer 访问新分配的内存:

+-------+        +------+        +---+---+---+---+---+
|&buffer+------->+buffer+------->+   |   |   |   |   |
+-------+        +---+--+        +---+---+---+---+---+

关于c - 为什么 getline 的第一个参数是指向指针 "char**"而不是 "char*"的指针?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5744393/

相关文章:

c - 矩阵乘法的自动向量化

c - 组织具有大量静态函数的 C 程序

Cloudant 的 C SDK?

c - 输出错误,无法理解为什么 C

c - 在 STM32F411 Discovery 上实现 HD44780 LCD 时调试 HardFault

在c编程中不能使用send()发送.exe

c++ - clang 与 gcc 和 msvc 中方法指针的模板

c - 错误 ID 返回 1 退出状态和 program.c :(. 文本+0xe):对 `clrscr' 的 undefined reference

javascript - JS : Can I call a function with same scope as caller or do macro-like behavior

javascript - 如何使用 javascript 或 jquery 运行放置在数组中的函数