问题
In [7.1.4 Use of library functions], I read :
Any function declared in a header may be additionally implemented as a function-like macro defined in the header...
and
Any invocation of a library function that is implemented as a macro shall expand to code that evaluates each of its arguments exactly once...
Then for getc
, [7.21.7.5 The getc function] :
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.
Does the definition of getc
:
- contradicts the library functions definition?
- the converse?
- is this an incoherence in the standard?
- or does this means that if
getc
is solely implemented (doesn't seems to be compliant but?) as a macro it may evaluate its argument twice?
回答1:
The definitions in the standard are coherent; your attempted interpretation of them is not completely coherent.
The Standard Says …
The ISO/IEC 9899:2011 (C11) standard says (quoting a bit more of the material from §7.1.4, and breaking parts of one big paragraph into several):
Each of the following statements applies unless explicitly stated otherwise in the detailed descriptions that follow: …
Any function declared in a header may be additionally implemented as a function-like macro defined in the header, so if a library function is declared explicitly when its header is included, one of the techniques shown below can be used to ensure the declaration is not affected by such a macro.
Any macro definition of a function can be suppressed locally by enclosing the name of the function in parentheses, because the name is then not followed by the left parenthesis that indicates expansion of a macro function name. For the same syntactic reason, it is permitted to take the address of a library function even if it is also defined as a macro.185) The use of
#undef
to remove any macro definition will also ensure that an actual function is referred to.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.186) Likewise, those function-like macros described in the following subclauses may be invoked in an expression anywhere a function with a compatible return type could be called.187)
185) This means that an implementation shall provide an actual function for each library function, even if it also provides a macro for that function.
186) Such macros might not contain the sequence points that the corresponding function calls do.
187) Because external identifiers and some macro names beginning with an underscore are reserved, implementations may provide special semantics for such names. For example, the identifier
_BUILTIN_abs
could be used to indicate generation of in-line code for theabs
function. Thus, the appropriate header could specify#define abs(x) _BUILTIN_abs(x)
for a compiler whose code generator will accept it. In this manner, a user desiring to guarantee that a given library function such as
abs
will be a genuine function may write#undef abs
whether the implementation’s header provides a macro implementation of
abs
or a built-in implementation. The prototype for the function, which precedes and is hidden by any macro definition, is thereby revealed also.
Note the contents of footnote 185, in particular.
You also quote the material from the definition of getc
from §7.21.7.5:
The
getc
function is equivalent tofgetc
, except that if it is implemented as a macro, it may evaluatestream
more than once, so the argument should never be an expression with side effects.
(Where stream
is the name used for the argument to getc
.)
Interpreting the Standard
You ask (slightly paraphrased):
Does the definition of
getc
contradict the library functions definition?No. The opening of section §7.1.4 says that 'unless explicitly stated otherwise', and then gives a series of general rules, and then the specification of
getc
explicitly states otherwise.Does the converse apply?
No. The opening section of §7.1.4 says that the specification of any particular function can override the generalities from §7.1.4.
Is this an incoherence in the standard?
I see no incoherence here.
Or does this mean that if
getc
is solely implemented as a macro (which doesn't seem to be compliant but…), the macro may evaluate its argument twice?getc
may not be implemented solely as a macro (footnote 185). There must also be an actual function that implements the same functionality. The implementation can be simple:int (getc)(FILE *fp) { return getc(fp); }
The macro implementing
getc
is explicitly allowed to evaluate its argument multiple times (but is not required to do so). The specification in §7.21.7.5 explicitly says that it may, and the specification in §7.1.4 explicitly says that §7.21.7.5 is allowed to change the general rule of §7.1.4 that normally forbids such behaviour.
回答2:
It's true that a getc
macro is likely to evaluate its fp
argument more than once. It might be good if §7.1.4 said "Unless otherwise noted, any invocation of a library function that is implemented as a macro shall expand to code that evaluates each of its arguments exactly once."
getc
implementations that evaluate their fp
argument multiple times go back to the dawn of stdio. So it's no surprise, and there's essentially no code out there that depends on single evaluation or would break under multiple evaluation. (Who ever writes anything like getc(*fpp++)
? Yes, I can come up with an example, and not even a 100% contrived one, but really, it's vanishingly rare.)
Code that really, really cares can always call fgetc
. That's what it's for.
来源:https://stackoverflow.com/questions/39793885/getc-as-macro-and-c-standard-library-function-definition-coherent