【问题标题】:Why fputc() when putc()?为什么在 putc() 时使用 fputc()?
【发布时间】:2013-11-20 20:32:15
【问题描述】:

getc()fgetc()

putc()fputc()

它们之间的主要区别是什么?

我听说这两个函数的作用几乎相同,只是 getc() 可以用作宏。这是什么意思?

如果它们相同,为什么要使用两个函数来做同样的事情?

任何帮助将不胜感激?

【问题讨论】:

    标签: c


    【解决方案1】:

    首先,printf 与 fprintf 不同:fprintf 支持文件参数,printf 到标准输出。

    使用 fputc 和 fgetc 的原因是 putc 和 getc 在历史实现中是多次评估参数的宏版本。例如the version on Unix V7:

    #define getc(p)   (--(p)->_cnt>=0? *(p)->_ptr++&0377:_filbuf(p))
    #define putc(x,p) (--(p)->_cnt>=0? ((int)(*(p)->_ptr++=(unsigned)(x))):_flsbuf((unsigned)(x),p))
    

    其中的每个“p”都被您放入参数中的表达式替换 - 所以如果它有副作用(比如您调用函数来获取文件,或者使用 ++ 遍历文件列表operator),它会被多次调用,并且可能对不同的文件进行操作。

    一些现代系统(例如 FreeBSD 或 OSX)仍然这样做,但通常仅在“解锁”版本中,因为标准 getc/putc 函数必须是线程安全的。未锁定的版本用于库函数内部的性能,因此在库函数的顶部只获取一次锁(这样当您调用 printf 时,它不必调用 fputc 数百次,每次执行一次锁时间)。

    【讨论】:

      【解决方案2】:

      根据 Kernighan 的书,putc 等同于 fputc,但 putc 可以实现为宏,并且 putc 可以多次评估其流参数。

      putc 和 fputc 之间的区别在于,使用 putc 时,您可能会运行本身不安全的宏版本,因为它可能需要多次评估其流参数。这会导致大多数人没有意识到的并发症,因此不会提防,因此最好使用 fputc。 fputc的宏没有这个问题。

      【讨论】:

      • 非 f 函数不是只是带有 stdin 预先提供的参数之一的宏吗?
      • @BitFiddlingCodeMonkey 不,我将在答案中添加一个示例
      【解决方案3】:

      至少对于fprintf(),这是显而易见的,因为可以指定FILE* 写入的位置。 printf() 打印到stdout

      其他 2X2 函数在使用方面确实是等效的。

      【讨论】:

        猜你喜欢
        • 2012-12-10
        • 2017-04-04
        • 2017-12-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-11-02
        • 2019-01-13
        • 1970-01-01
        相关资源
        最近更新 更多