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

📄 cpp.texi

📁 理解和实践操作系统的一本好书
💻 TEXI
📖 第 1 页 / 共 5 页
字号:
minimize confusion for people reading your program.@node Wrapper Headers@section Wrapper Headers@cindex wrapper headers@cindex overriding a header file@findex #include_nextSometimes it is necessary to adjust the contents of a system-providedheader file without editing it directly.  GCC's @command{fixincludes}operation does this, for example.  One way to do that would be to createa new header file with the same name and insert it in the search pathbefore the original header.  That works fine as long as you're willingto replace the old header entirely.  But what if you want to refer tothe old header from the new one?You cannot simply include the old header with @samp{#include}.  Thatwill start from the beginning, and find your new header again.  If yourheader is not protected from multiple inclusion (@pxref{Once-OnlyHeaders}), it will recurse infinitely and cause a fatal error.You could include the old header with an absolute pathname:@smallexample#include "/usr/include/old-header.h"@end smallexample@noindentThis works, but is not clean; should the system headers ever move, youwould have to edit the new headers to match.There is no way to solve this problem within the C standard, but you canuse the GNU extension @samp{#include_next}.  It means, ``Include the@emph{next} file with this name''.  This directive works like@samp{#include} except in searching for the specified file: it startssearching the list of header file directories @emph{after} the directoryin which the current file was found.Suppose you specify @option{-I /usr/local/include}, and the list ofdirectories to search also includes @file{/usr/include}; and supposeboth directories contain @file{signal.h}.  Ordinary @code{@w{#include<signal.h>}} finds the file under @file{/usr/local/include}.  If thatfile contains @code{@w{#include_next <signal.h>}}, it starts searchingafter that directory, and finds the file in @file{/usr/include}.@samp{#include_next} does not distinguish between @code{<@var{file}>}and @code{"@var{file}"} inclusion, nor does it check that the file youspecify has the same name as the current file.  It simply looks for thefile named, starting with the directory in the search path after the onewhere the current file was found.The use of @samp{#include_next} can lead to great confusion.  Werecommend it be used only when there is no other alternative.  Inparticular, it should not be used in the headers belonging to a specificprogram; it should be used only to make global corrections along thelines of @command{fixincludes}.@node System Headers@section System Headers@cindex system header filesThe header files declaring interfaces to the operating system andruntime libraries often cannot be written in strictly conforming C@.Therefore, GCC gives code found in @dfn{system headers} specialtreatment.  All warnings, other than those generated by @samp{#warning}(@pxref{Diagnostics}), are suppressed while GCC is processing a systemheader.  Macros defined in a system header are immune to a few warningswherever they are expanded.  This immunity is granted on an ad-hocbasis, when we find that a warning generates lots of false positivesbecause of code in macros defined in system headers.Normally, only the headers found in specific directories are consideredsystem headers.  These directories are determined when GCC is compiled.There are, however, two ways to make normal headers into system headers.The @option{-isystem} command line option adds its argument to the list ofdirectories to search for headers, just like @option{-I}.  Any headersfound in that directory will be considered system headers.All directories named by @option{-isystem} are searched @emph{after} alldirectories named by @option{-I}, no matter what their order was on thecommand line.  If the same directory is named by both @option{-I} and@option{-isystem}, the @option{-I} option is ignored.  GCC provides aninformative message when this occurs if @option{-v} is used.@findex #pragma GCC system_headerThere is also a directive, @code{@w{#pragma GCC system_header}}, whichtells GCC to consider the rest of the current include file a systemheader, no matter where it was found.  Code that comes before the@samp{#pragma} in the file will not be affected.  @code{@w{#pragma GCCsystem_header}} has no effect in the primary source file.On very old systems, some of the pre-defined system header directoriesget even more special treatment.  GNU C++ considers code in headersfound in those directories to be surrounded by an @code{@w{extern "C"}}block.  There is no way to request this behavior with a @samp{#pragma},or from the command line.@node Macros@chapter MacrosA @dfn{macro} is a fragment of code which has been given a name.Whenever the name is used, it is replaced by the contents of the macro.There are two kinds of macros.  They differ mostly in what they looklike when they are used.  @dfn{Object-like} macros resemble data objectswhen used, @dfn{function-like} macros resemble function calls.You may define any valid identifier as a macro, even if it is a Ckeyword.  The preprocessor does not know anything about keywords.  Thiscan be useful if you wish to hide a keyword such as @code{const} from anolder compiler that does not understand it.  However, the preprocessoroperator @code{defined} (@pxref{Defined}) can never be defined as amacro, and C++'s named operators (@pxref{C++ Named Operators}) cannot bemacros when you are compiling C++.@menu* Object-like Macros::* Function-like Macros::* Macro Arguments::* Stringification::* Concatenation::* Variadic Macros::* Predefined Macros::* Undefining and Redefining Macros::* Directives Within Macro Arguments::* Macro Pitfalls::@end menu@node Object-like Macros@section Object-like Macros@cindex object-like macro@cindex symbolic constants@cindex manifest constantsAn @dfn{object-like macro} is a simple identifier which will be replacedby a code fragment.  It is called object-like because it looks like adata object in code that uses it.  They are most commonly used to givesymbolic names to numeric constants.@findex #defineYou create macros with the @samp{#define} directive.  @samp{#define} isfollowed by the name of the macro and then the token sequence it shouldbe an abbreviation for, which is variously referred to as the macro's@dfn{body}, @dfn{expansion} or @dfn{replacement list}.  For example,@smallexample#define BUFFER_SIZE 1024@end smallexample@noindentdefines a macro named @code{BUFFER_SIZE} as an abbreviation for thetoken @code{1024}.  If somewhere after this @samp{#define} directivethere comes a C statement of the form@smallexamplefoo = (char *) malloc (BUFFER_SIZE);@end smallexample@noindentthen the C preprocessor will recognize and @dfn{expand} the macro@code{BUFFER_SIZE}.  The C compiler will see the same tokens as it wouldif you had written@smallexamplefoo = (char *) malloc (1024);@end smallexampleBy convention, macro names are written in uppercase.  Programs areeasier to read when it is possible to tell at a glance which names aremacros.The macro's body ends at the end of the @samp{#define} line.  You maycontinue the definition onto multiple lines, if necessary, usingbackslash-newline.  When the macro is expanded, however, it will allcome out on one line.  For example,@smallexample#define NUMBERS 1, \                2, \                3int x[] = @{ NUMBERS @};     @expansion{} int x[] = @{ 1, 2, 3 @};@end smallexample@noindentThe most common visible consequence of this is surprising line numbersin error messages.There is no restriction on what can go in a macro body provided itdecomposes into valid preprocessing tokens.  Parentheses need notbalance, and the body need not resemble valid C code.  (If it does not,you may get error messages from the C compiler when you use the macro.)The C preprocessor scans your program sequentially.  Macro definitionstake effect at the place you write them.  Therefore, the following inputto the C preprocessor@smallexamplefoo = X;#define X 4bar = X;@end smallexample@noindentproduces@smallexamplefoo = X;bar = 4;@end smallexampleWhen the preprocessor expands a macro name, the macro's expansionreplaces the macro invocation, then the expansion is examined for moremacros to expand.  For example,@smallexample@group#define TABLESIZE BUFSIZE#define BUFSIZE 1024TABLESIZE     @expansion{} BUFSIZE     @expansion{} 1024@end group@end smallexample@noindent@code{TABLESIZE} is expanded first to produce @code{BUFSIZE}, then thatmacro is expanded to produce the final result, @code{1024}.Notice that @code{BUFSIZE} was not defined when @code{TABLESIZE} wasdefined.  The @samp{#define} for @code{TABLESIZE} uses exactly theexpansion you specify---in this case, @code{BUFSIZE}---and does notcheck to see whether it too contains macro names.  Only when you@emph{use} @code{TABLESIZE} is the result of its expansion scanned formore macro names.This makes a difference if you change the definition of @code{BUFSIZE}at some point in the source file.  @code{TABLESIZE}, defined as shown,will always expand using the definition of @code{BUFSIZE} that iscurrently in effect:@smallexample#define BUFSIZE 1020#define TABLESIZE BUFSIZE#undef BUFSIZE#define BUFSIZE 37@end smallexample@noindentNow @code{TABLESIZE} expands (in two stages) to @code{37}.If the expansion of a macro contains its own name, either directly orvia intermediate macros, it is not expanded again when the expansion isexamined for more macros.  This prevents infinite recursion.@xref{Self-Referential Macros}, for the precise details.@node Function-like Macros@section Function-like Macros@cindex function-like macrosYou can also define macros whose use looks like a function call.  Theseare called @dfn{function-like macros}.  To define a function-like macro,you use the same @samp{#define} directive, but you put a pair ofparentheses immediately after the macro name.  For example,@smallexample#define lang_init()  c_init()lang_init()     @expansion{} c_init()@end smallexampleA function-like macro is only expanded if its name appears with a pairof parentheses after it.  If you write just the name, it is left alone.This can be useful when you have a function and a macro of the samename, and you wish to use the function sometimes.@smallexampleextern void foo(void);#define foo() /* @r{optimized inline version} */@dots{}  foo();  funcptr = foo;@end smallexampleHere the call to @code{foo()} will use the macro, but the functionpointer will get the address of the real function.  If the macro were tobe expanded, it would cause a syntax error.If you put spaces between the macro name and the parentheses in themacro definition, that does not define a function-like macro, it definesan object-like macro whose expansion happens to begin with a pair ofparentheses.@smallexample#define lang_init ()    c_init()lang_init()     @expansion{} () c_init()()@end smallexampleThe first two pairs of parentheses in this expansion come from themacro.  The third is the pair that was originally after the macroinvocation.  Since @code{lang_init} is an object-like macro, it does notconsume those parentheses.@node Macro Arguments@section Macro Arguments@cindex arguments@cindex macros with arguments@cindex arguments in macro definitionsFunction-like macros can take @dfn{arguments}, just like true functions.To define a macro that uses arguments, you insert @dfn{parameters}between the pair of parentheses in the macro definition that make themacro function-like.  The parameters must be valid C identifiers,separated by commas and optionally whitespace.To invoke a macro that takes arguments, you write the name of the macrofollowed by a list of @dfn{actual arguments} in parentheses, separatedby commas.  The invocation of the macro need not be restricted to asingle logical line---it can cross as many lines in the source file asyou wish.  The number of arguments you give must match the number ofparameters in the macro definition.  When the macro is expanded, eachuse of a parameter in its body is replaced by the tokens of thecorresponding argument.  (You need not use all of the parameters in themacro body.)As an example, here is a macro that computes the minimum of two numericvalues, as it is defined in many C programs, and some uses.@smallexample#define min(X, Y)  ((X) < (Y) ? (X) : (Y))  x = min(a, b);          @expansion{}  x = ((a) < (b) ? (a) : (b));  y = min(1, 2);          @expansion{}  y = ((1) < (2) ? (1) : (2));  z = min(a + 28, *p);    @expansion{}  z = ((a + 28) < (*p) ? (a + 28) : (*p));@end smallexample@noindent(In this small example you can already see several of the dangers ofmacro arguments.  @xref{Macro Pitfalls}, for detailed explanations.)Leading and trailing whitespace in each argument is dropped, and allwhitespace between the tokens of an argument is reduced to a singlespace.  Parentheses within each argument must balance; a comma withinsuch parentheses does not end the argument.  However, there is norequirement for square brackets or braces to balance, and they do notprevent a comma from separating arguments.  Thus,@smallexamplemacro (array[x = y, x + 1])

⌨️ 快捷键说明

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