3

我正在维护某人的代码,如下所示:

FILE *db_fp = NULL;
bstring data = NULL;

db_fp = db_open(DB_FILE, "r");
LOG_CHECK(db_fp == NULL, "Failed to open database: %s", DB_FILE);

data = bread((bNread)fread, db_fp);
LOG_CHECK(data == NULL, "Failed to read from db file: %s", DB_FILE);

db_close(db_fp);

return data;

我在理解以下行时遇到了一些麻烦:

data = bread((bNread)fread, db_fp);

我可以猜到,它正在从以下文件指针中获取一个 bstream 并返回一个 bstring。然而,我想知道面包和面包。

bread 包含 2 个参数,一个函数指针 (bNread) 和文件指针。但我不确定我是否理解它是如何工作的。

4

2 回答 2

5

bread()更好的字符串库文档中的声明是:

typedef size_t (*bNread)(void *buff, size_t elsize, size_t nelem, void *parm);
extern bstring bread(bNread readPtr, void *parm);

因此,bread()是一个将指向函数的指针作为参数的函数。bNreadtype 用于指定函数的类型。该fread()函数足够接近,可以在强制转换时通过集合——匹配并不精确,因为它FILE *的第四个参数需要 a ,而 a 指向的类型的真正函数bNread需要 a void *。的第二个参数bread是作为第四个参数传递给 . 指向的函数的值bNread

因此,在您维护的代码中:

data = bread((bNread)fread, db_fp);

Better String Library 函数fread()作为 I/O 函数调用,转换为正确的类型以平息编译器对类型不匹配的警告,以及应该用于读取的文件流。


bread()函数的实现在需要执行 I/O 以读取字符串时使用函数指针和流指针。也就是说,正如 KerrekB 还解释的那样,代码可能会写成这样:

char buffer[256];

size_t nbytes = (*readPtr)(buffer, sizeof(char), sizeof(buffer), parm);

或(等效地):

size_t nbytes = readPtr(buffer, sizeof(char), sizeof(buffer), parm);

(如果你很久以前就学过 C,第一种是通过函数指针调用函数的唯一方法;自从产生了 C89 标准后,第二种已经可用,而且现在可能使用得更广泛。)有许多实现必须担心的技巧,但基本的函数调用会有些相似。代码可以使用除 之外的 I/O 函数fread(),但函数的接口必须相似。

指向函数的指针很强大,但在你使用它们之前是晦涩难懂的。

于 2012-11-18T16:47:15.113 回答
3

这是一种可能的实现bread

bstring bread(int(*func)(void *, size_t, size_t ,FILE *), FILE * fp)
{
    char buf[10];
    bstring result;

    func(buf, 10, 1, fp);
    return result;
}

这当然不能反映真正的功能bread在做什么,但它应该让您了解实现如何使用它。

(真正的函数当然会先读取一个长度fp,然后为字符串分配足够的内存,然后读取字符串,但细节取决于它是什么bstring以及它是如何工作的。真正的实现也会检查func! )

于 2012-11-18T16:27:50.070 回答