Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

3 лет назад
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
  2. <html>
  3. <!-- Created by GNU Texinfo 6.5, http://www.gnu.org/software/texinfo/ -->
  4. <head>
  5. <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  6. <title>Guard Macros (The GNU C Preprocessor Internals)</title>
  7. <meta name="description" content="Guard Macros (The GNU C Preprocessor Internals)">
  8. <meta name="keywords" content="Guard Macros (The GNU C Preprocessor Internals)">
  9. <meta name="resource-type" content="document">
  10. <meta name="distribution" content="global">
  11. <meta name="Generator" content="makeinfo">
  12. <link href="index.html#Top" rel="start" title="Top">
  13. <link href="Concept-Index.html#Concept-Index" rel="index" title="Concept Index">
  14. <link href="index.html#SEC_Contents" rel="contents" title="Table of Contents">
  15. <link href="index.html#Top" rel="up" title="Top">
  16. <link href="Files.html#Files" rel="next" title="Files">
  17. <link href="Line-Numbering.html#Line-Numbering" rel="prev" title="Line Numbering">
  18. <style type="text/css">
  19. <!--
  20. a.summary-letter {text-decoration: none}
  21. blockquote.indentedblock {margin-right: 0em}
  22. blockquote.smallindentedblock {margin-right: 0em; font-size: smaller}
  23. blockquote.smallquotation {font-size: smaller}
  24. div.display {margin-left: 3.2em}
  25. div.example {margin-left: 3.2em}
  26. div.lisp {margin-left: 3.2em}
  27. div.smalldisplay {margin-left: 3.2em}
  28. div.smallexample {margin-left: 3.2em}
  29. div.smalllisp {margin-left: 3.2em}
  30. kbd {font-style: oblique}
  31. pre.display {font-family: inherit}
  32. pre.format {font-family: inherit}
  33. pre.menu-comment {font-family: serif}
  34. pre.menu-preformatted {font-family: serif}
  35. pre.smalldisplay {font-family: inherit; font-size: smaller}
  36. pre.smallexample {font-size: smaller}
  37. pre.smallformat {font-family: inherit; font-size: smaller}
  38. pre.smalllisp {font-size: smaller}
  39. span.nolinebreak {white-space: nowrap}
  40. span.roman {font-family: initial; font-weight: normal}
  41. span.sansserif {font-family: sans-serif; font-weight: normal}
  42. ul.no-bullet {list-style: none}
  43. -->
  44. </style>
  45. </head>
  46. <body lang="en">
  47. <a name="Guard-Macros"></a>
  48. <div class="header">
  49. <p>
  50. Next: <a href="Files.html#Files" accesskey="n" rel="next">Files</a>, Previous: <a href="Line-Numbering.html#Line-Numbering" accesskey="p" rel="prev">Line Numbering</a>, Up: <a href="index.html#Top" accesskey="u" rel="up">Top</a> &nbsp; [<a href="index.html#SEC_Contents" title="Table of contents" rel="contents">Contents</a>][<a href="Concept-Index.html#Concept-Index" title="Index" rel="index">Index</a>]</p>
  51. </div>
  52. <hr>
  53. <a name="The-Multiple_002dInclude-Optimization"></a>
  54. <h2 class="unnumbered">The Multiple-Include Optimization</h2>
  55. <a name="index-guard-macros"></a>
  56. <a name="index-controlling-macros"></a>
  57. <a name="index-multiple_002dinclude-optimization"></a>
  58. <p>Header files are often of the form
  59. </p>
  60. <div class="smallexample">
  61. <pre class="smallexample">#ifndef FOO
  62. #define FOO
  63. &hellip;
  64. #endif
  65. </pre></div>
  66. <p>to prevent the compiler from processing them more than once. The
  67. preprocessor notices such header files, so that if the header file
  68. appears in a subsequent <code>#include</code> directive and <code>FOO</code> is
  69. defined, then it is ignored and it doesn&rsquo;t preprocess or even re-open
  70. the file a second time. This is referred to as the <em>multiple
  71. include optimization</em>.
  72. </p>
  73. <p>Under what circumstances is such an optimization valid? If the file
  74. were included a second time, it can only be optimized away if that
  75. inclusion would result in no tokens to return, and no relevant
  76. directives to process. Therefore the current implementation imposes
  77. requirements and makes some allowances as follows:
  78. </p>
  79. <ol>
  80. <li> There must be no tokens outside the controlling <code>#if</code>-<code>#endif</code>
  81. pair, but whitespace and comments are permitted.
  82. </li><li> There must be no directives outside the controlling directive pair, but
  83. the <em>null directive</em> (a line containing nothing other than a single
  84. &lsquo;<samp>#</samp>&rsquo; and possibly whitespace) is permitted.
  85. </li><li> The opening directive must be of the form
  86. <div class="smallexample">
  87. <pre class="smallexample">#ifndef FOO
  88. </pre></div>
  89. <p>or
  90. </p>
  91. <div class="smallexample">
  92. <pre class="smallexample">#if !defined FOO [equivalently, #if !defined(FOO)]
  93. </pre></div>
  94. </li><li> In the second form above, the tokens forming the <code>#if</code> expression
  95. must have come directly from the source file&mdash;no macro expansion must
  96. have been involved. This is because macro definitions can change, and
  97. tracking whether or not a relevant change has been made is not worth the
  98. implementation cost.
  99. </li><li> There can be no <code>#else</code> or <code>#elif</code> directives at the outer
  100. conditional block level, because they would probably contain something
  101. of interest to a subsequent pass.
  102. </li></ol>
  103. <p>First, when pushing a new file on the buffer stack,
  104. <code>_stack_include_file</code> sets the controlling macro <code>mi_cmacro</code> to
  105. <code>NULL</code>, and sets <code>mi_valid</code> to <code>true</code>. This indicates
  106. that the preprocessor has not yet encountered anything that would
  107. invalidate the multiple-include optimization. As described in the next
  108. few paragraphs, these two variables having these values effectively
  109. indicates top-of-file.
  110. </p>
  111. <p>When about to return a token that is not part of a directive,
  112. <code>_cpp_lex_token</code> sets <code>mi_valid</code> to <code>false</code>. This
  113. enforces the constraint that tokens outside the controlling conditional
  114. block invalidate the optimization.
  115. </p>
  116. <p>The <code>do_if</code>, when appropriate, and <code>do_ifndef</code> directive
  117. handlers pass the controlling macro to the function
  118. <code>push_conditional</code>. cpplib maintains a stack of nested conditional
  119. blocks, and after processing every opening conditional this function
  120. pushes an <code>if_stack</code> structure onto the stack. In this structure
  121. it records the controlling macro for the block, provided there is one
  122. and we&rsquo;re at top-of-file (as described above). If an <code>#elif</code> or
  123. <code>#else</code> directive is encountered, the controlling macro for that
  124. block is cleared to <code>NULL</code>. Otherwise, it survives until the
  125. <code>#endif</code> closing the block, upon which <code>do_endif</code> sets
  126. <code>mi_valid</code> to true and stores the controlling macro in
  127. <code>mi_cmacro</code>.
  128. </p>
  129. <p><code>_cpp_handle_directive</code> clears <code>mi_valid</code> when processing any
  130. directive other than an opening conditional and the null directive.
  131. With this, and requiring top-of-file to record a controlling macro, and
  132. no <code>#else</code> or <code>#elif</code> for it to survive and be copied to
  133. <code>mi_cmacro</code> by <code>do_endif</code>, we have enforced the absence of
  134. directives outside the main conditional block for the optimization to be
  135. on.
  136. </p>
  137. <p>Note that whilst we are inside the conditional block, <code>mi_valid</code> is
  138. likely to be reset to <code>false</code>, but this does not matter since
  139. the closing <code>#endif</code> restores it to <code>true</code> if appropriate.
  140. </p>
  141. <p>Finally, since <code>_cpp_lex_direct</code> pops the file off the buffer stack
  142. at <code>EOF</code> without returning a token, if the <code>#endif</code> directive
  143. was not followed by any tokens, <code>mi_valid</code> is <code>true</code> and
  144. <code>_cpp_pop_file_buffer</code> remembers the controlling macro associated
  145. with the file. Subsequent calls to <code>stack_include_file</code> result in
  146. no buffer being pushed if the controlling macro is defined, effecting
  147. the optimization.
  148. </p>
  149. <p>A quick word on how we handle the
  150. </p>
  151. <div class="smallexample">
  152. <pre class="smallexample">#if !defined FOO
  153. </pre></div>
  154. <p>case. <code>_cpp_parse_expr</code> and <code>parse_defined</code> take steps to see
  155. whether the three stages &lsquo;<samp>!</samp>&rsquo;, &lsquo;<samp>defined-expression</samp>&rsquo; and
  156. &lsquo;<samp>end-of-directive</samp>&rsquo; occur in order in a <code>#if</code> expression. If
  157. so, they return the guard macro to <code>do_if</code> in the variable
  158. <code>mi_ind_cmacro</code>, and otherwise set it to <code>NULL</code>.
  159. <code>enter_macro_context</code> sets <code>mi_valid</code> to false, so if a macro
  160. was expanded whilst parsing any part of the expression, then the
  161. top-of-file test in <code>push_conditional</code> fails and the optimization
  162. is turned off.
  163. </p>
  164. <hr>
  165. <div class="header">
  166. <p>
  167. Next: <a href="Files.html#Files" accesskey="n" rel="next">Files</a>, Previous: <a href="Line-Numbering.html#Line-Numbering" accesskey="p" rel="prev">Line Numbering</a>, Up: <a href="index.html#Top" accesskey="u" rel="up">Top</a> &nbsp; [<a href="index.html#SEC_Contents" title="Table of contents" rel="contents">Contents</a>][<a href="Concept-Index.html#Concept-Index" title="Index" rel="index">Index</a>]</p>
  168. </div>
  169. </body>
  170. </html>