⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cpp.html

📁 vxworks相关论文
💻 HTML
📖 第 1 页 / 共 5 页
字号:
  SKIP_SPACES (p, lim);else ...</PRE><P>The presence of two statements--the compound statement and a nullstatement--in between the <SAMP>`if'</SAMP> condition and the <SAMP>`else'</SAMP>makes invalid C code.</P><P>The definition of the macro <SAMP>`SKIP_SPACES'</SAMP> can be altered to solvethis problem, using a <SAMP>`do ... while'</SAMP> statement.  Here is how:</P><PRE>#define SKIP_SPACES (p, limit)     \do { register char *lim = (limit); \     while (p != lim) {            \       if (*p++ != ' ') {          \         p--; break; }}}           \while (0)</PRE><P>Now <SAMP>`SKIP_SPACES (p, lim);'</SAMP> expands into</P><PRE>do {...} while (0);</PRE><P>which is one statement.</P><H4><A NAME="SEC23" HREF="cpp_toc.html#TOC23">Duplication of Side Effects</A></H4><P><A NAME="IDX63"></A><A NAME="IDX64"></A>Many C programs define a macro <SAMP>`min'</SAMP>, for "minimum", like this:</P><PRE>#define min(X, Y)  ((X) &#60; (Y) ? (X) : (Y))</PRE><P>When you use this macro with an argument containing a side effect,as shown here,</P><PRE>next = min (x + y, foo (z));</PRE><P>it expands as follows:</P><PRE>next = ((x + y) &#60; (foo (z)) ? (x + y) : (foo (z)));</PRE><P>where <SAMP>`x + y'</SAMP> has been substituted for <SAMP>`X'</SAMP> and <SAMP>`foo (z)'</SAMP>for <SAMP>`Y'</SAMP>.</P><P>The function <SAMP>`foo'</SAMP> is used only once in the statement as it appearsin the program, but the expression <SAMP>`foo (z)'</SAMP> has been substitutedtwice into the macro expansion.  As a result, <SAMP>`foo'</SAMP> might be calledtwo times when the statement is executed.  If it has side effects orif it takes a long time to compute, the results might not be what youintended.  We say that <SAMP>`min'</SAMP> is an <EM>unsafe</EM> macro.</P><P>The best solution to this problem is to define <SAMP>`min'</SAMP> in a way thatcomputes the value of <SAMP>`foo (z)'</SAMP> only once.  The C language offers nostandard way to do this, but it can be done with GNU C extensions asfollows:</P><PRE>#define min(X, Y)                     \({ typeof (X) __x = (X), __y = (Y);   \   (__x &#60; __y) ? __x : __y; })</PRE><P>If you do not wish to use GNU C extensions, the only solution is to becareful when <EM>using</EM> the macro <SAMP>`min'</SAMP>.  For example, you cancalculate the value of <SAMP>`foo (z)'</SAMP>, save it in a variable, and use thatvariable in <SAMP>`min'</SAMP>:</P><PRE>#define min(X, Y)  ((X) &#60; (Y) ? (X) : (Y))...{  int tem = foo (z);  next = min (x + y, tem);}</PRE><P>(where we assume that <SAMP>`foo'</SAMP> returns type <SAMP>`int'</SAMP>).</P><H4><A NAME="SEC24" HREF="cpp_toc.html#TOC24">Self-Referential Macros</A></H4><P><A NAME="IDX65"></A>A <EM>self-referential</EM> macro is one whose name appears in its definition.A special feature of ANSI Standard C is that the self-reference is notconsidered a macro call.  It is passed into the preprocessor outputunchanged.</P><P>Let's consider an example:</P><PRE>#define foo (4 + foo)</PRE><P>where <SAMP>`foo'</SAMP> is also a variable in your program.</P><P>Following the ordinary rules, each reference to <SAMP>`foo'</SAMP> will expand into<SAMP>`(4 + foo)'</SAMP>; then this will be rescanned and will expand into <SAMP>`(4+ (4 + foo))'</SAMP>; and so on until it causes a fatal error (memory full) in thepreprocessor.</P><P>However, the special rule about self-reference cuts this process shortafter one step, at <SAMP>`(4 + foo)'</SAMP>.  Therefore, this macro definitionhas the possibly useful effect of causing the program to add 4 tothe value of <SAMP>`foo'</SAMP> wherever <SAMP>`foo'</SAMP> is referred to.</P><P>In most cases, it is a bad idea to take advantage of this feature.  Aperson reading the program who sees that <SAMP>`foo'</SAMP> is a variable willnot expect that it is a macro as well.  The reader will come across theidentifier <SAMP>`foo'</SAMP> in the program and think its value should be thatof the variable <SAMP>`foo'</SAMP>, whereas in fact the value is four greater.</P><P>The special rule for self-reference applies also to <EM>indirect</EM>self-reference.  This is the case where a macro <VAR>x</VAR> expands to use amacro <SAMP>`y'</SAMP>, and the expansion of <SAMP>`y'</SAMP> refers to the macro<SAMP>`x'</SAMP>.  The resulting reference to <SAMP>`x'</SAMP> comes indirectly from theexpansion of <SAMP>`x'</SAMP>, so it is a self-reference and is not furtherexpanded.  Thus, after</P><PRE>#define x (4 + y)#define y (2 * x)</PRE><P><SAMP>`x'</SAMP> would expand into <SAMP>`(4 + (2 * x))'</SAMP>.  Clear?</P><P>But suppose <SAMP>`y'</SAMP> is used elsewhere, not from the definition of <SAMP>`x'</SAMP>.Then the use of <SAMP>`x'</SAMP> in the expansion of <SAMP>`y'</SAMP> is not a self-referencebecause <SAMP>`x'</SAMP> is not "in progress".  So it does expand.  However,the expansion of <SAMP>`x'</SAMP> contains a reference to <SAMP>`y'</SAMP>, and thatis an indirect self-reference now because <SAMP>`y'</SAMP> is "in progress".The result is that <SAMP>`y'</SAMP> expands to <SAMP>`(2 * (4 + y))'</SAMP>.</P><P>It is not clear that this behavior would ever be useful, but it is specifiedby the ANSI C standard, so you may need to understand it.</P><H4><A NAME="SEC25" HREF="cpp_toc.html#TOC25">Separate Expansion of Macro Arguments</A></H4><P><A NAME="IDX66"></A><A NAME="IDX67"></A><A NAME="IDX68"></A></P><P>We have explained that the expansion of a macro, including the substitutedactual arguments, is scanned over again for macro calls to be expanded.</P><P>What really happens is more subtle: first each actual argument text is scannedseparately for macro calls.  Then the results of this are substituted intothe macro body to produce the macro expansion, and the macro expansionis scanned again for macros to expand.</P><P>The result is that the actual arguments are scanned <EM>twice</EM> to expandmacro calls in them.</P><P>Most of the time, this has no effect.  If the actual argument containedany macro calls, they are expanded during the first scan.  The resulttherefore contains no macro calls, so the second scan does not change it.If the actual argument were substituted as given, with no prescan,the single remaining scan would find the same macro calls and producethe same results.</P><P>You might expect the double scan to change the results when aself-referential macro is used in an actual argument of another macro(see section <A HREF="cpp.html#SEC24">Self-Referential Macros</A>): the self-referential macro would be expanded oncein the first scan, and a second time in the second scan.  But this is notwhat happens.  The self-references that do not expand in the first scan aremarked so that they will not expand in the second scan either.</P><P>The prescan is not done when an argument is stringified or concatenated.Thus,</P><PRE>#define str(s) #s#define foo 4str (foo)</PRE><P>expands to <SAMP>`"foo"'</SAMP>.  Once more, prescan has been prevented fromhaving any noticeable effect.</P><P>More precisely, stringification and concatenation use the argument aswritten, in un-prescanned form.  The same actual argument would be used inprescanned form if it is substituted elsewhere without stringification orconcatenation.</P><PRE>#define str(s) #s lose(s)#define foo 4str (foo)</PRE><P>expands to <SAMP>`"foo" lose(4)'</SAMP>.</P><P>You might now ask, "Why mention the prescan, if it makes no difference?And why not skip it and make the preprocessor faster?"  The answer isthat the prescan does make a difference in three special cases:</P><UL><LI>Nested calls to a macro.<LI>Macros that call other macros that stringify or concatenate.<LI>Macros whose expansions contain unshielded commas.</UL><P>We say that <EM>nested</EM> calls to a macro occur when a macro's actualargument contains a call to that very macro.  For example, if <SAMP>`f'</SAMP>is a macro that expects one argument, <SAMP>`f (f (1))'</SAMP> is a nestedpair of calls to <SAMP>`f'</SAMP>.  The desired expansion is made byexpanding <SAMP>`f (1)'</SAMP> and substituting that into the definition of<SAMP>`f'</SAMP>.  The prescan causes the expected result to happen.Without the prescan, <SAMP>`f (1)'</SAMP> itself would be substituted asan actual argument, and the inner use of <SAMP>`f'</SAMP> would appearduring the main scan as an indirect self-reference and would notbe expanded.  Here, the prescan cancels an undesirable side effect(in the medical, not computational, sense of the term) of the specialrule for self-referential macros.</P><P>But prescan causes trouble in certain other cases of nested macro calls.Here is an example:</P><PRE>#define foo  a,b#define bar(x) lose(x)#define lose(x) (1 + (x))bar(foo)</PRE><P>We would like <SAMP>`bar(foo)'</SAMP> to turn into <SAMP>`(1 + (foo))'</SAMP>, whichwould then turn into <SAMP>`(1 + (a,b))'</SAMP>.  But instead, <SAMP>`bar(foo)'</SAMP>expands into <SAMP>`lose(a,b)'</SAMP>, and you get an error because <CODE>lose</CODE>requires a single argument.  In this case, the problem is easily solvedby the same parentheses that ought to be used to prevent misnesting ofarithmetic operations:</P><PRE>#define foo (a,b)#define bar(x) lose((x))</PRE><P>The problem is more serious when the operands of the macro are notexpressions; for example, when they are statements.  Then parenthesesare unacceptable because they would make for invalid C code:</P><PRE>#define foo { int a, b; ... }</PRE><P>In GNU C you can shield the commas using the <SAMP>`({...})'</SAMP>construct which turns a compound statement into an expression:</P><PRE>#define foo ({ int a, b; ... })</PRE><P>Or you can rewrite the macro definition to avoid such commas:</P><PRE>#define foo { int a; int b; ... }</PRE><P>There is also one case where prescan is useful.  It is possibleto use prescan to expand an argument and then stringify it--if you usetwo levels of macros.  Let's add a new macro <SAMP>`xstr'</SAMP> to theexample shown above:</P><PRE>#define xstr(s) str(s)#define str(s) #s#define foo 4xstr (foo)</PRE><P>This expands into <SAMP>`"4"'</SAMP>, not <SAMP>`"foo"'</SAMP>.  The reason for thedifference is that the argument of <SAMP>`xstr'</SAMP> is expanded at prescan(because <SAMP>`xstr'</SAMP> does not specify stringification or concatenation ofthe argument).  The result of prescan then forms the actual argument for<SAMP>`str'</SAMP>.  <SAMP>`str'</SAMP> uses its argument without prescan because itperforms stringification; but it cannot prevent or undo the prescanningalready done by <SAMP>`xstr'</SAMP>.</P><H4><A NAME="SEC26" HREF="cpp_toc.html#TOC26">Cascaded Use of Macros</A></H4><P><A NAME="IDX69"></A><A NAME="IDX70"></A>A <EM>cascade</EM> of macros is when one macro's body contains a referenceto another macro.  This is very common practice.  For example,</P><PRE>#define BUFSIZE 1020#define TABLESIZE BUFSIZE</PRE><P>This is not at all the same as defining <SAMP>`TABLESIZE'</SAMP> to be <SAMP>`1020'</SAMP>.The <SAMP>`#define'</SAMP> for <SAMP>`TABLESIZE'</SAMP> uses exactly t

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -