getc()作为宏和C标准库函数的定义,相干? [英] getc() as macro and C standard library function definition, coherent?

查看:463
本文介绍了getc()作为宏和C标准库函数的定义,相干?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

[7.1.4使用库函数] 中,我读到:


一个头文件可以被另外实现为头文件中定义的一个
函数类的宏...


任何被实现为宏
的库函数的调用都应该扩展为代码,它将每个参数精确地评估一次。

然后为 getc [7.21.7.5 getc函数
$ b


getc函数等同于fgetc,除非如果
被实现为宏,它可能会多次评估流,所以
参数不应该是一个带有副作用的表达式。


定义 getc




  • 与库函数定义相矛盾?

  • 相反?

  • 这是标准中的不一致吗?

  • 或者这是否意味着如果单独实现 getc t似乎是兼容的,但?)作为一个宏,它可以评估它的参数两次?
  • >标准中的定义是连贯的;你的尝试对它们的解释并不是完全一致的。



    标准说明...



    ISO / IEC 9899: 2011(C11)标准说(引用更多来自§7.1.4的材料,并将一个大段的部分分成几个):


    除非在以下详细的
    描述中另有明确说明,否则以下每个声明均适用:......

    在头文件中声明的任何函数都可以额外实现作为头文件中定义的类似于函数的宏,因此,如果在包含头文件时明确声明了库函数,则可以使用下面显示的技术之一来确保声明不受此类宏影响。



    函数的任何宏定义都可以通过将函数的名称括在圆括号中进行局部抑制,因为名称后面没有跟着左括号,表示扩展了宏函数名字。出于同样的语法原因,即使它也被定义为一个宏,也可以使用库函数的地址。 185) #undef 删除任何宏定义也将确保引用实际函数。



    任何调用实现为
    a宏的库函数应该扩展为只对一个参数进行一次评估的代码,必要时用圆括号完全保护,所以使用任意表达式作为参数通常是安全的。同样,这些类似函数的宏在任何可以调用具有兼容返回类型的函数的表达式中,可以调用以下子句:

    185)这意味着一个实现应该为每个库函数提供一个实际的函数,即使
    也为该函数提供了一个宏。



    < sup> 186)这样的宏可能不会包含相应函数调用的顺序点。



    187)由于外部标识符和一些以下划线开头的宏名称是保留的,可能会为这些名称提供特殊的语义。例如,标识符 _BUILTIN_abs 可用于指示 abs 函数的内嵌代码的生成。因此,适当的头文件可以指定

      #define abs(x)_BUILTIN_abs(x)

    代码生成器将接受它的编译器。以这种方式,希望保证诸如 abs 的给定库函数将是真正函数的用户可以写入

      #undef abs 

    实现的头文件是否提供宏执行 abs 或内置实现。这个函数的原型在任何宏定义的前面并且被任何宏定义隐藏,因此也被揭示出来。

    注意脚注185的内容,特别是。

    您还引用了来自§7.21.7.5的 getc 定义中的材料:


    getc 函数相当于 fgetc ,但是如果它被实现为一个宏,它可能不止一次地评估 stream ,所以参数不应该是一个带有副作用的表达式。


    (其中 stream 是用于参数<



    解读标准



    你问(略微转述):


    • getc 的定义是否与库函数相矛盾定义?



      没有。 §7.1.4节的开头部分说'除非另有明确规定',然后给出一系列一般规则,然后 getc 的规范另外明确指出。 / p>


    • 是否适用?



      §7.1.4的开头部分表明,任何特定函数的规范都可以覆盖§7.1.4中的一般性。


    • 这是一个在标准中不一致?



      我在这里没有看到任何不一致的情况。

    • >或者这是否意味着如果 getc 完全是作为一个宏实现的(这似乎不符合但是...),宏可以评估它的两次参数? em>


      1. getc 不能单独实现为宏脚注185)。还必须有一个实现相同功能的实际功能。实现可以很简单:

          int(getc)(FILE * fp){return getc(fp); } 


      2. 执行 getc 明确允许多次评估其参数(但不是必须这样做)。 §7.21.7.5中的规范明确指出它可以,并且§7.1.4中的规范明确规定§7.21.7.5可以改变§7.1.4的通常禁止这种行为的一般规则。




    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?

    解决方案

    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 the abs 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 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.

    (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?

      1. 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); }
        

      2. 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.

    这篇关于getc()作为宏和C标准库函数的定义,相干?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆