52

我在任何地方都看到“它实际上是相同的”,或者类似的东西......

来自GNU C 编程教程

GNU C 库中还有一个名为 fgetc 的函数。它在大多数方面与 getc 相同,只是 getc 通常实现为宏函数并且经过高度优化,因此在大多数情况下更可取。(在您从标准输入读取的情况下,getc 与 fgetc 一样快,因为与计算机读取输入的速度相比,人类打字速度较慢,但​​是当您从非人类交互式生成的流中读取时, fgetc 可能更好。)

其他的区别是什么?我听说它们每个都有不同的实现(并且可以用作宏),但是,是什么让它们如此不同(或足够不同)以使它们都在标准 C 库(或规范)中?

4

3 回答 3

54

来自Advanced Programming in Unix Environment

...

getc和之间的区别在于fgetc可以getc实现为宏,而fgetc不能实现为宏。这意味着三件事:

  • to 的参数getc不应是具有副作用的表达式。
  • 既然fgetc保证是一个函数,我们就可以取它的地址。这允许我们将地址fgetc作为参数传递给另一个函数。
  • 调用 fgetc 可能需要比调用更长的时间getc,因为调用函数通常需要更多时间。

...

于 2013-08-28T06:48:01.367 回答
21

在 99.9% 的情况下,这些差异似乎毫无意义。

可能会有所作为的一点 -手册页getc() may be implemented as a macro which evaluates stream more than once

在某些(不是很有用)情况下,它可能会导致奇怪的行为,例如:

FILE *my_files[10] = {...}, *f=&my_files[0];
for (i=0; i<10; i++) {
    int c = getc(f++);    // Parameter to getc has side effects!
}

如果getc计算f++不止一次,则f每次迭代都会推进不止一次。相比之下,fgetc在这种情况下是安全的。

于 2013-08-28T07:26:01.840 回答
3

本质上是相同的(或相似到不打扰)。你应该看看他们的实现:GNU libcMUSL libc是自由软件实现。它们现在可以实现为内联函数(与宏一样快)。

而且我不会那么麻烦。在现实生活中,I/O 主要受硬件限制(例如访问磁盘的时间)。

于 2013-08-28T06:44:04.050 回答