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

📄 cpp.texi

📁 gcc库的原代码,对编程有很大帮助.
💻 TEXI
📖 第 1 页 / 共 5 页
字号:
@subsubsection Unintended Grouping of Arithmetic@cindex parentheses in macro bodiesYou may have noticed that in most of the macro definition examples shownabove, each occurrence of a macro argument name had parentheses around it.In addition, another pair of parentheses usually surround the entire macrodefinition.  Here is why it is best to write macros that way.Suppose you define a macro as follows,@example#define ceil_div(x, y) (x + y - 1) / y@end example@noindentwhose purpose is to divide, rounding up.  (One use for this operation isto compute how many @samp{int} objects are needed to hold a certainnumber of @samp{char} objects.)  Then suppose it is used as follows:@examplea = ceil_div (b & c, sizeof (int));@end example@noindentThis expands into@examplea = (b & c + sizeof (int) - 1) / sizeof (int);@end example@noindentwhich does not do what is intended.  The operator-precedence rules ofC make it equivalent to this:@examplea = (b & (c + sizeof (int) - 1)) / sizeof (int);@end example@noindentBut what we want is this:@examplea = ((b & c) + sizeof (int) - 1)) / sizeof (int);@end example@noindentDefining the macro as@example#define ceil_div(x, y) ((x) + (y) - 1) / (y)@end example@noindentprovides the desired result.However, unintended grouping can result in another way.  Consider@samp{sizeof ceil_div(1, 2)}.  That has the appearance of a C expressionthat would compute the size of the type of @samp{ceil_div (1, 2)}, but infact it means something very different.  Here is what it expands to:@examplesizeof ((1) + (2) - 1) / (2)@end example@noindentThis would take the size of an integer and divide it by two.  The precedencerules have put the division outside the @samp{sizeof} when it was intendedto be inside.Parentheses around the entire macro definition can prevent such problems.Here, then, is the recommended way to define @samp{ceil_div}:@example#define ceil_div(x, y) (((x) + (y) - 1) / (y))@end example@node Swallow Semicolon, Side Effects, Macro Parentheses, Macro Pitfalls@subsubsection Swallowing the Semicolon@cindex semicolons (after macro calls)Often it is desirable to define a macro that expands into a compoundstatement.  Consider, for example, the following macro, that advances apointer (the argument @samp{p} says where to find it) across whitespacecharacters:@example#define SKIP_SPACES (p, limit)  \@{ register char *lim = (limit); \  while (p != lim) @{            \    if (*p++ != ' ') @{          \      p--; break; @}@}@}@end example@noindentHere Backslash-Newline is used to split the macro definition, which mustbe a single line, so that it resembles the way such C code would belaid out if not part of a macro definition.A call to this macro might be @samp{SKIP_SPACES (p, lim)}.  Strictlyspeaking, the call expands to a compound statement, which is a completestatement with no need for a semicolon to end it.  But it looks like afunction call.  So it minimizes confusion if you can use it like a functioncall, writing a semicolon afterward, as in @samp{SKIP_SPACES (p, lim);}But this can cause trouble before @samp{else} statements, because thesemicolon is actually a null statement.  Suppose you write@exampleif (*p != 0)  SKIP_SPACES (p, lim);else @dots{}@end example@noindentThe presence of two statements---the compound statement and a nullstatement---in between the @samp{if} condition and the @samp{else}makes invalid C code.The definition of the macro @samp{SKIP_SPACES} can be altered to solvethis problem, using a @samp{do @dots{} while} statement.  Here is how:@example#define SKIP_SPACES (p, limit)     \do @{ register char *lim = (limit); \     while (p != lim) @{            \       if (*p++ != ' ') @{          \         p--; break; @}@}@}           \while (0)@end exampleNow @samp{SKIP_SPACES (p, lim);} expands into@exampledo @{@dots{}@} while (0);@end example@noindentwhich is one statement.@node Side Effects, Self-Reference, Swallow Semicolon, Macro Pitfalls@subsubsection Duplication of Side Effects@cindex side effects (in macro arguments)@cindex unsafe macrosMany C programs define a macro @samp{min}, for ``minimum'', like this:@example#define min(X, Y)  ((X) < (Y) ? (X) : (Y))@end exampleWhen you use this macro with an argument containing a side effect,as shown here,@examplenext = min (x + y, foo (z));@end example@noindentit expands as follows:@examplenext = ((x + y) < (foo (z)) ? (x + y) : (foo (z)));@end example@noindentwhere @samp{x + y} has been substituted for @samp{X} and @samp{foo (z)}for @samp{Y}.The function @samp{foo} is used only once in the statement as it appearsin the program, but the expression @samp{foo (z)} has been substitutedtwice into the macro expansion.  As a result, @samp{foo} 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} is an @dfn{unsafe} macro.The best solution to this problem is to define @samp{min} in a way thatcomputes the value of @samp{foo (z)} only once.  The C language offers nostandard way to do this, but it can be done with GNU C extensions asfollows:@example#define min(X, Y)                     \(@{ typeof (X) __x = (X), __y = (Y);   \   (__x < __y) ? __x : __y; @})@end exampleIf you do not wish to use GNU C extensions, the only solution is to becareful when @emph{using} the macro @samp{min}.  For example, you cancalculate the value of @samp{foo (z)}, save it in a variable, and use thatvariable in @samp{min}:@example#define min(X, Y)  ((X) < (Y) ? (X) : (Y))@dots{}@{  int tem = foo (z);  next = min (x + y, tem);@}@end example@noindent(where we assume that @samp{foo} returns type @samp{int}).@node Self-Reference, Argument Prescan, Side Effects, Macro Pitfalls@subsubsection Self-Referential Macros@cindex self-referenceA @dfn{self-referential} 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.Let's consider an example:@example#define foo (4 + foo)@end example@noindentwhere @samp{foo} is also a variable in your program.Following the ordinary rules, each reference to @samp{foo} will expand into@samp{(4 + foo)}; then this will be rescanned and will expand into @samp{(4+ (4 + foo))}; and so on until it causes a fatal error (memory full) in thepreprocessor.However, the special rule about self-reference cuts this process shortafter one step, at @samp{(4 + foo)}.  Therefore, this macro definitionhas the possibly useful effect of causing the program to add 4 tothe value of @samp{foo} wherever @samp{foo} is referred to.In most cases, it is a bad idea to take advantage of this feature.  Aperson reading the program who sees that @samp{foo} is a variable willnot expect that it is a macro as well.  The reader will come across theidentifier @samp{foo} in the program and think its value should be thatof the variable @samp{foo}, whereas in fact the value is four greater.The special rule for self-reference applies also to @dfn{indirect}self-reference.  This is the case where a macro @var{x} expands to use amacro @samp{y}, and the expansion of @samp{y} refers to the macro@samp{x}.  The resulting reference to @samp{x} comes indirectly from theexpansion of @samp{x}, so it is a self-reference and is not furtherexpanded.  Thus, after@example#define x (4 + y)#define y (2 * x)@end example@noindent@samp{x} would expand into @samp{(4 + (2 * x))}.  Clear?But suppose @samp{y} is used elsewhere, not from the definition of @samp{x}.Then the use of @samp{x} in the expansion of @samp{y} is not a self-referencebecause @samp{x} is not ``in progress''.  So it does expand.  However,the expansion of @samp{x} contains a reference to @samp{y}, and thatis an indirect self-reference now because @samp{y} is ``in progress''.The result is that @samp{y} expands to @samp{(2 * (4 + y))}.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.@node Argument Prescan, Cascaded Macros, Self-Reference, Macro Pitfalls@subsubsection Separate Expansion of Macro Arguments@cindex expansion of arguments@cindex macro argument expansion@cindex prescan of macro argumentsWe have explained that the expansion of a macro, including the substitutedactual arguments, is scanned over again for macro calls to be expanded.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.The result is that the actual arguments are scanned @emph{twice} to expandmacro calls in them.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.You might expect the double scan to change the results when aself-referential macro is used in an actual argument of another macro(@pxref{Self-Reference}): 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.The prescan is not done when an argument is stringified or concatenated.Thus,@example#define str(s) #s#define foo 4str (foo)@end example@noindentexpands to @samp{"foo"}.  Once more, prescan has been prevented fromhaving any noticeable effect.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.@example#define str(s) #s lose(s)#define foo 4str (foo)@end exampleexpands to @samp{"foo" lose(4)}.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:@itemize @bullet@itemNested calls to a macro.@itemMacros that call other macros that stringify or concatenate.@itemMacros whose expansions contain unshielded commas.@end itemizeWe say that @dfn{nested} calls to a macro occur when a macro's actualargument contains a call to that very macro.  For example, if @samp{f}is a macro that expects one argument, @samp{f (f (1))} is a nestedpair of calls to @samp{f}.  The desired expansion is made byexpanding @samp{f (1)} and substituting that into the definition of@samp{f}.  The prescan causes the expected result to happen.Without the prescan, @samp{f (1)} itself would be substituted asan actual argument, and the inner use of @samp{f} would appearduring the main scan as an indirect self-reference a

⌨️ 快捷键说明

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