How does the C preprocessor handle circular dependencies?

前端 未结 5 1279
无人共我
无人共我 2021-02-01 11:59

I want to know how the C preprocessor handles circular dependencies (of #defines). This is my program:

#define ONE TWO 
#define TWO THREE
#defi         


        
5条回答
  •  北恋
    北恋 (楼主)
    2021-02-01 12:37

    While a preprocessor macro is being expanded, that macro's name is not expanded. So all three of your symbols are defined as themselves:

    ONE -> TWO -> THREE -> ONE (not expanded because expansion of ONE is in progress)
    TWO -> THREE -> ONE -> TWO (        "                         TWO      "        )
    THREE -> ONE -> TWO -> THREE (      "                         THREE    "        )
    

    This behaviour is set by §6.10.3.4 of the C standard (section number from the C11 draft, although as far as I know, the wording and numbering of the section is unchanged since C89). When a macro name is encountered, it is replaced with its definition (and # and ## preprocessor operators are dealt with, as well as parameters to function-like macros). Then the result is rescanned for more macros (in the context of the rest of the file):

    2/ If the name of the macro being replaced is found during this scan of the replacement list (not including the rest of the source file’s preprocessing tokens), it is not replaced. Furthermore, if any nested replacements encounter the name of the macro being replaced, it is not replaced…

    The clause goes on to say that any token which is not replaced because of a recursive call is effectively "frozen": it will never be replaced:

    … These nonreplaced macro name preprocessing tokens are no longer available for further replacement even if they are later (re)examined in contexts in which that macro name preprocessing token would otherwise have been replaced.

    The situation which the last sentence refers rarely comes up in practice, but here is the simplest case I could think of:

    #define two one,two
    #define a(x) b(x)
    #define b(x,y) x,y
    a(two)
    

    The result is one, two. two is expanded to one,two during the replacement of a, and the expanded two is marked as completely expanded. Subsequently, b(one,two) is expanded. This is no longer in the context of the replacement of two, but the two which is the second argument of b has been frozen, so it is not expanded again.

提交回复
热议问题