关于C#:getc是宏还是函数?

Is getc a macro or a function?

我试图找出getcfgetc 之间的区别。当时我看到这样的说法:

The difference between getc and fgetc is that getc can be implemented as a macro, whereas fgetc cannot be implemented as a macro.

那么,getc 真的是一个函数还是一个宏?如果是宏,它会调用其他函数。那么,getc 是否在 C 中实现?


The difference between getc and fgetc is that getc can be implemented as a macro, whereas fgetc cannot be implemented as a macro.

那是不正确的。

除了少数例外,任何 C 标准库函数都可以另外实现为宏,但该宏的编写方式存在一些限制(因此宏仍可以像函数一样使用)。

引用 N1570 第 7.1.4 节:

Any function declared in a header may be additionally implemented as a
function-like macro defined in the header, [...] Any invocation of a
library function that is implemented as a macro shall expand to code
that evaluates each of its arguments exactly once, fully protected by
parentheses where necessary, so it is generally safe to use arbitrary
expressions as arguments.

getc 的特别之处在于其中一项限制可以放宽(7.21.7.5):

The getc function is equivalent to fgetc, except that if
it is implemented as a macro, it may evaluate stream more than
once, so the argument should never be an expression with side effects.

fgetcgetc的声明是:

1
2
int fgetc(FILE *stream);
int getc(FILE *stream);

stream 参数(例如,在像 fgetc(stdin)getc(file) 这样的调用中几乎总是一个没有副作用的表达式,但规则仍然禁止将 fgetc 定义为对其参数求值超过一次,以防程序员编写类似 fgetc(file_list[i++]) 之类的东西。对于 getc,该规则被放宽,以便可以将其定义为宏(在某些情况下可以显着提高效率),同时可能会破坏类似 .

fgetc 的情况下,将其实现为宏而不是仅仅作为函数可能不会有太多优势。关键是标准明确允许它。

So, is getc implemented in C or not?

也许吧。任何 C 库函数都不需要在 C 中实现。某些函数可以用汇编程序或任何其他语言实现 - 或者它们可能是编译器内在函数。通常大多数或所有 C 标准库函数都是用 C 实现的,但标准只指定它们的工作方式,而不是它们的编写方式。


getc 是 C99 标准第 7.21.7.5 节中所述的函数,可能会或可能不会作为宏实现:

The getc function is equivalent to fgetc, except that if it is implemented as a macro, it may evaluate stream more than once, so the argument should never be an expression with side effects.

它不适用于具有副作用的参数。例如 --

1
int c = getc(*fpp++);