我正在阅读Kernighan编写的C编程书,遇到了putc
和fputc
。我不太了解两者之间的区别,或者什么时候可以使用另一种。我在StackOverflow上找到了一些有关该主题的帖子,但仍不清楚。
如这里提到的(putc needs stdout, vs puts):
问题:
putc
可以实现为宏,但是使用fputc
会有什么问题呢?putc
多次评估其参数。因此,与评估论点相比,它具有什么优点或缺点。最佳答案
宏实现的问题是,如果任何参数有副作用,则可能会对这些副作用进行多次评估,从而可能导致不确定的行为。考虑以下玩具示例:
#define SQUARE(x) ((x) * (x))
在大多数情况下,这将按预期运行,但是如果您传递诸如
f()
这样的表达式,则调用f()
函数的副作用将发生两次,而不是一次,因为预处理器只是一个文本转换器,而忽略C:int f()
{
printf("f() was called\n");
return 42;
}
...
int x = SQUARE(f()); // This calls f() twice! It gets expanded to this:
// int x = (f() * f());
为了更好地理解这一点,如果将
putc
函数实现为宏,则可以多次评估其stream
参数。因此,如果该流来自一个函数:FILE *get_file()
{
// Potential side effects could happen here
return some_file;
}
...
putc('A', get_file());
然后,这可能导致函数
get_file()
被多次调用,并可能产生有害的副作用。当然,解决方案是只调用常规函数,例如
fputc()
而不是putc()
。由于它不是宏,因此多次评估其参数没有任何潜在的问题。宏有时可能很危险,因此请谨慎使用。