Getc () how is the definition of the macro and C standard library coherent?

In [7.1.4 Using Library Functions] , I read:

Any function declared in the header can be further implemented as a functionally similar macro defined in the header ...

and

Any call to a library function implemented as a macro expands to code that evaluates each of its arguments exactly once ...

Then for getc , [7.21.7.5 getc function] :

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

Does the definition of getc define:

  • contrary to the definition of library functions?
  • the opposite?
  • Is incoherence in the standard?
  • or does this mean that if getc is implemented exclusively (not like compatibility, but?) as a macro, can it evaluate its argument twice?
+5
source share
2 answers

Definitions in the standard are coherent; your attempt to interpret them is not completely consistent.

The standard says ...

ISO / IEC 9899: 2011 (C11) states (quoting a little more material from 7.1.4 and breaking parts of one large paragraph into several):

Each of the following statements applies, unless explicitly stated otherwise in the detailed description that follows: ...

Any function declared in the header can be additionally implemented as a functionally similar macro defined in the header, therefore, if the library function is declared explicitly when the header is enabled, you can use one of the methods shown below to ensure such a macro does not affect ad.

Any macro definition of a function can be suppressed locally by entering the name of the function in parentheses, because the left bracket does not follow this name, which indicates the extension of the name of the macro function function. 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) Using #undef to remove any macro definition will also ensure that the actual function is mentioned.

Any call to a library function that is implemented as a macro must be expanded to a code that evaluates each of its arguments exactly once, completely protected by brackets, where necessary, therefore it is generally safe to use arbitrary expressions as arguments. 186) Similarly, these functionally similar macros described in the following subsections can be called in an expression where a function with a compatible return type can be called. 187)

185) This means that an implementation must provide an actual function for each library function, even if it also provides a macro for that function.

186) Such macros may not contain sequence points that make the corresponding function calls.

187) Because external identifiers and some macro names starting with an underscore are reserved, implementations may provide special semantics for such names. For example, the identifier _BUILTIN_abs can be used to indicate the generation of inline code for the abs function. Thus, the corresponding heading can indicate

 #define abs(x) _BUILTIN_abs(x) 

for a compiler whose code generator will accept it. Thus, a user who wants to ensure that a given library function, such as abs , is a genuine function, can write

 #undef abs 

whether the implementation header provides an abs macro implementation or an inline implementation. Thus, the prototype of the function, preceding and hidden by any macro definition, is also disclosed.

Note the contents of footnote 185 in particular.

You also cite material from the definition of getc from clause 7.21.7.5:

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

(Where stream is the name used for the getc argument.)

Interpretation of the standard

You ask (slightly rephrased):

  • Does getc define library function definitions?

    No. The opening of Β§7.1.4 states that β€œunless explicitly stated otherwise,” and then gives a series of general rules, and then the getc specification explicitly indicates otherwise.

  • Is the converse used?

    No. The first section of clause 7.1.4 states that the specification of a particular function may override the general provisions of clause 7.1.4.

  • Is this incoherence in the standard?

    I do not see incoherence here.

  • Or does this mean that if getc is implemented solely as a macro (which does not seem to be compatible, but ...), can the macro evaluate its argument twice?

    • getc can be implemented not only as a macro (footnote 185). There must also be an actual function that implements the same functionality. The implementation may be simple:

       int (getc)(FILE *fp) { return getc(fp); } 
    • The getc macro processing getc explicitly allowed to evaluate its argument multiple times (but this is not required). The specification contained in clause 7.21.7.5 explicitly says that it can, and the specification in clause 7.1.4 explicitly states that in Β§7.21.7.5 it is allowed to modify the general rule of clause 7.1.4, which usually prohibits such behavior .

+3
source

It is true that the getc macro will most likely evaluate its fp argument more than once. It would be nice if in Β§7.1.4 it was said: "Unless otherwise indicated, any call to the library function, implemented as a macro, should be expanded to code that evaluates each of its arguments exactly once."

getc , which repeatedly evaluate the fp argument, returns to stdio dawn. Therefore, it is not surprising, and there, in fact, there is no code that depends on a single assessment or will be divided into several ratings. (Who ever writes something like getc(*fpp++) ? Yes, I can come up with an example and not even 100% contrived, but in fact it rarely disappears.)

Code that really, really cares can always call fgetc . What is this for.

+2
source

Source: https://habr.com/ru/post/1257534/


All Articles