我在 Chromium-os/glibc中查看fread的源代码,对此越来越感到困惑。
首先,我对 fread 被声明为一个宏的方式感到惊讶,它带有函数名,然后是它的参数,最后是它的参数类型:
/* Read NMEMB chunks of SIZE bytes each from STREAM into P. */
size_t
DEFUN(fread, (p, size, nmemb, stream),
PTR p AND size_t size AND size_t nmemb AND register FILE *stream)
Run Code Online (Sandbox Code Playgroud)
这背后的理由是什么,为什么不
size_t fread(PTR p, size_t size, size_t nmemb, register FILE * stream)
Run Code Online (Sandbox Code Playgroud)
哪个更具可读性?
我对这一行特别困惑:
int c = __fillbf(stream);
Run Code Online (Sandbox Code Playgroud)
并且在任何地方都找不到这个功能。我认为这可能是一个我还不知道的系统调用,但它不是表的一部分
那么背后的真正代码是__fill_bf(register FILE *)什么?
编辑:感谢DYP的宏定义,Crowman的__fillbf和雷的解释漂亮的合成!
ps:也欢迎任何关于 fread 棘手部分的额外解释的答案!
在 ANSI 标准化之前,函数声明具有不同的语法:
ANSI 声明:
int f(int x, double y) {
...
}
Run Code Online (Sandbox Code Playgroud)
ANSI (K&R1) 之前的声明:
f(x, y)
int x;
double y;
{
...
}
Run Code Online (Sandbox Code Playgroud)
像这样的宏DEFUN通常是为可能需要由非常旧的编译器编译的程序定义的。(现在已经不太常见了,因为 ANSI 标准化早在 1989 年就已经实现了。)如果使用 ANSI/ISO C,将有一个文件以一种方式定义宏,如果使用 ANSI C 之前的版本,则以另一种方式定义宏。(对于 chromiumos,这将是ansidecl) .h .) DEFUN 调用将因此扩展为适合所使用的编译器的 decl 格式。
正如 Crowman 在评论中提到的那样, 的定义__fillbf在insides.c中。看起来它会将一组字符读入内部缓冲区,因此fgetc可以一次读取一个字符,而无需每次都进行磁盘访问。