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

📄 extend.texi

📁 理解和实践操作系统的一本好书
💻 TEXI
📖 第 1 页 / 共 5 页
字号:
                             &&hack - &&foo @};goto *(&&foo + array[i]);@end smallexample@noindentThis is more friendly to code living in shared libraries, as it reducesthe number of dynamic relocations that are needed, and by consequence,allows the data to be read-only.The @code{&&foo} expressions for the same label might have different valuesif the containing function is inlined or cloned.  If a program relies onthem being always the same, @code{__attribute__((__noinline__))} shouldbe used to prevent inlining.  If @code{&&foo} is usedin a static variable initializer, inlining is forbidden.@node Nested Functions@section Nested Functions@cindex nested functions@cindex downward funargs@cindex thunksA @dfn{nested function} is a function defined inside another function.(Nested functions are not supported for GNU C++.)  The nested function'sname is local to the block where it is defined.  For example, here wedefine a nested function named @code{square}, and call it twice:@smallexample@groupfoo (double a, double b)@{  double square (double z) @{ return z * z; @}  return square (a) + square (b);@}@end group@end smallexampleThe nested function can access all the variables of the containingfunction that are visible at the point of its definition.  This iscalled @dfn{lexical scoping}.  For example, here we show a nestedfunction which uses an inherited variable named @code{offset}:@smallexample@groupbar (int *array, int offset, int size)@{  int access (int *array, int index)    @{ return array[index + offset]; @}  int i;  /* @r{@dots{}} */  for (i = 0; i < size; i++)    /* @r{@dots{}} */ access (array, i) /* @r{@dots{}} */@}@end group@end smallexampleNested function definitions are permitted within functions in the placeswhere variable definitions are allowed; that is, in any block, mixedwith the other declarations and statements in the block.It is possible to call the nested function from outside the scope of itsname by storing its address or passing the address to another function:@smallexamplehack (int *array, int size)@{  void store (int index, int value)    @{ array[index] = value; @}  intermediate (store, size);@}@end smallexampleHere, the function @code{intermediate} receives the address of@code{store} as an argument.  If @code{intermediate} calls @code{store},the arguments given to @code{store} are used to store into @code{array}.But this technique works only so long as the containing function(@code{hack}, in this example) does not exit.If you try to call the nested function through its address after thecontaining function has exited, all hell will break loose.  If you tryto call it after a containing scope level has exited, and if it refersto some of the variables that are no longer in scope, you may be lucky,but it's not wise to take the risk.  If, however, the nested functiondoes not refer to anything that has gone out of scope, you should besafe.GCC implements taking the address of a nested function using a techniquecalled @dfn{trampolines}.  A paper describing them is available as@noindent@uref{http://people.debian.org/~aaronl/Usenix88-lexic.pdf}.A nested function can jump to a label inherited from a containingfunction, provided the label was explicitly declared in the containingfunction (@pxref{Local Labels}).  Such a jump returns instantly to thecontaining function, exiting the nested function which did the@code{goto} and any intermediate functions as well.  Here is an example:@smallexample@groupbar (int *array, int offset, int size)@{  __label__ failure;  int access (int *array, int index)    @{      if (index > size)        goto failure;      return array[index + offset];    @}  int i;  /* @r{@dots{}} */  for (i = 0; i < size; i++)    /* @r{@dots{}} */ access (array, i) /* @r{@dots{}} */  /* @r{@dots{}} */  return 0; /* @r{Control comes here from @code{access}    if it detects an error.}  */ failure:  return -1;@}@end group@end smallexampleA nested function always has no linkage.  Declaring one with@code{extern} or @code{static} is erroneous.  If you need to declare the nested functionbefore its definition, use @code{auto} (which is otherwise meaninglessfor function declarations).@smallexamplebar (int *array, int offset, int size)@{  __label__ failure;  auto int access (int *, int);  /* @r{@dots{}} */  int access (int *array, int index)    @{      if (index > size)        goto failure;      return array[index + offset];    @}  /* @r{@dots{}} */@}@end smallexample@node Constructing Calls@section Constructing Function Calls@cindex constructing calls@cindex forwarding callsUsing the built-in functions described below, you can recordthe arguments a function received, and call another functionwith the same arguments, without knowing the number or typesof the arguments.You can also record the return value of that function call,and later return that value, without knowing what data typethe function tried to return (as long as your caller expectsthat data type).However, these built-in functions may interact badly with somesophisticated features or other extensions of the language.  Itis, therefore, not recommended to use them outside very simplefunctions acting as mere forwarders for their arguments.@deftypefn {Built-in Function} {void *} __builtin_apply_args ()This built-in function returns a pointer to datadescribing how to perform a call with the same arguments as were passedto the current function.The function saves the arg pointer register, structure value address,and all registers that might be used to pass arguments to a functioninto a block of memory allocated on the stack.  Then it returns theaddress of that block.@end deftypefn@deftypefn {Built-in Function} {void *} __builtin_apply (void (*@var{function})(), void *@var{arguments}, size_t @var{size})This built-in function invokes @var{function}with a copy of the parameters described by @var{arguments}and @var{size}.The value of @var{arguments} should be the value returned by@code{__builtin_apply_args}.  The argument @var{size} specifies the sizeof the stack argument data, in bytes.This function returns a pointer to data describinghow to return whatever value was returned by @var{function}.  The datais saved in a block of memory allocated on the stack.It is not always simple to compute the proper value for @var{size}.  Thevalue is used by @code{__builtin_apply} to compute the amount of datathat should be pushed on the stack and copied from the incoming argumentarea.@end deftypefn@deftypefn {Built-in Function} {void} __builtin_return (void *@var{result})This built-in function returns the value described by @var{result} fromthe containing function.  You should specify, for @var{result}, a valuereturned by @code{__builtin_apply}.@end deftypefn@deftypefn {Built-in Function} __builtin_va_arg_pack ()This built-in function represents all anonymous arguments of an inlinefunction.  It can be used only in inline functions which will be alwaysinlined, never compiled as a separate function, such as those using@code{__attribute__ ((__always_inline__))} or@code{__attribute__ ((__gnu_inline__))} extern inline functions.It must be only passed as last argument to some other functionwith variable arguments.  This is useful for writing small wrapperinlines for variable argument functions, when using preprocessormacros is undesirable.  For example:@smallexampleextern int myprintf (FILE *f, const char *format, ...);extern inline __attribute__ ((__gnu_inline__)) intmyprintf (FILE *f, const char *format, ...)@{  int r = fprintf (f, "myprintf: ");  if (r < 0)    return r;  int s = fprintf (f, format, __builtin_va_arg_pack ());  if (s < 0)    return s;  return r + s;@}@end smallexample@end deftypefn@deftypefn {Built-in Function} __builtin_va_arg_pack_len ()This built-in function returns the number of anonymous arguments ofan inline function.  It can be used only in inline functions whichwill be always inlined, never compiled as a separate function, suchas those using @code{__attribute__ ((__always_inline__))} or@code{__attribute__ ((__gnu_inline__))} extern inline functions.For example following will do link or runtime checking of openarguments for optimized code:@smallexample#ifdef __OPTIMIZE__extern inline __attribute__((__gnu_inline__)) intmyopen (const char *path, int oflag, ...)@{  if (__builtin_va_arg_pack_len () > 1)    warn_open_too_many_arguments ();  if (__builtin_constant_p (oflag))    @{      if ((oflag & O_CREAT) != 0 && __builtin_va_arg_pack_len () < 1)        @{          warn_open_missing_mode ();          return __open_2 (path, oflag);        @}      return open (path, oflag, __builtin_va_arg_pack ());    @}      if (__builtin_va_arg_pack_len () < 1)    return __open_2 (path, oflag);  return open (path, oflag, __builtin_va_arg_pack ());@}#endif@end smallexample@end deftypefn@node Typeof@section Referring to a Type with @code{typeof}@findex typeof@findex sizeof@cindex macros, types of argumentsAnother way to refer to the type of an expression is with @code{typeof}.The syntax of using of this keyword looks like @code{sizeof}, but theconstruct acts semantically like a type name defined with @code{typedef}.There are two ways of writing the argument to @code{typeof}: with anexpression or with a type.  Here is an example with an expression:@smallexampletypeof (x[0](1))@end smallexample@noindentThis assumes that @code{x} is an array of pointers to functions;the type described is that of the values of the functions.Here is an example with a typename as the argument:@smallexampletypeof (int *)@end smallexample@noindentHere the type described is that of pointers to @code{int}.If you are writing a header file that must work when included in ISO Cprograms, write @code{__typeof__} instead of @code{typeof}.@xref{Alternate Keywords}.A @code{typeof}-construct can be used anywhere a typedef name could beused.  For example, you can use it in a declaration, in a cast, or insideof @code{sizeof} or @code{typeof}.@code{typeof} is often useful in conjunction with thestatements-within-expressions feature.  Here is how the two together canbe used to define a safe ``maximum'' macro that operates on anyarithmetic type and evaluates each of its arguments exactly once:@smallexample#define max(a,b) \  (@{ typeof (a) _a = (a); \      typeof (b) _b = (b); \    _a > _b ? _a : _b; @})@end smallexample@cindex underscores in variables in macros@cindex @samp{_} in variables in macros@cindex local variables in macros@cindex variables, local, in macros@cindex macros, local variables inThe reason for using names that start with underscores for the localvariables is to avoid conflicts with variable names that occur within theexpressions that are substituted for @code{a} and @code{b}.  Eventually wehope to design a new form of declaration syntax that allows you to declarevariables whose scopes start only after their initializers; this will be amore reliable way to prevent such conflicts.@noindentSome more examples of the use of @code{typeof}:@itemize @bullet@itemThis declares @code{y} with the type of what @code{x} points to.@smallexampletypeof (*x) y;@end smallexample@itemThis declares @code{y} as an array of such values.@smallexampletypeof (*x) y[4];@end smallexample@itemThis declares @code{y} as an array of pointers to characters:@smallexampletypeof (typeof (char *)[4]) y;@end smallexample@noindentIt is equivalent to the following traditional C declaration:@smallexamplechar *y[4];@end smallexampleTo see the meaning of the declaration using @code{typeof}, and why itmight be a useful way to write, rewrite it with these macros:@smallexample#define pointer(T)  typeof(T *)

⌨️ 快捷键说明

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