我正在阅读Kernighan编写的C编程书,遇到了putcfputc。我不太了解两者之间的区别,或者什么时候可以使用另一种。我在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()。由于它不是宏,因此多次评估其参数没有任何潜在的问题。宏有时可能很危险,因此请谨慎使用。

    09-17 20:10