【发布时间】:2013-11-20 20:32:15
【问题描述】:
getc() 与 fgetc()
putc() 与 fputc()
它们之间的主要区别是什么?
我听说这两个函数的作用几乎相同,只是 getc() 可以用作宏。这是什么意思?
如果它们相同,为什么要使用两个函数来做同样的事情?
任何帮助将不胜感激?
【问题讨论】:
标签: c
getc() 与 fgetc()
putc() 与 fputc()
它们之间的主要区别是什么?
我听说这两个函数的作用几乎相同,只是 getc() 可以用作宏。这是什么意思?
如果它们相同,为什么要使用两个函数来做同样的事情?
任何帮助将不胜感激?
【问题讨论】:
标签: c
首先,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 数百次,每次执行一次锁时间)。
【讨论】:
根据 Kernighan 的书,putc 等同于 fputc,但 putc 可以实现为宏,并且 putc 可以多次评估其流参数。
putc 和 fputc 之间的区别在于,使用 putc 时,您可能会运行本身不安全的宏版本,因为它可能需要多次评估其流参数。这会导致大多数人没有意识到的并发症,因此不会提防,因此最好使用 fputc。 fputc的宏没有这个问题。
【讨论】:
stdin 预先提供的参数之一的宏吗?
至少对于fprintf(),这是显而易见的,因为可以指定FILE* 写入的位置。 printf() 打印到stdout。
其他 2X2 函数在使用方面确实是等效的。
【讨论】: