📄 extend.texi
字号:
goto *(&&foo + array[i]);
@end example
@noindent
This is more friendly to code living in shared libraries, as it reduces
the number of dynamic relocations that are needed, and by consequence,
allows the data to be read-only.
@node Nested Functions
@section Nested Functions
@cindex nested functions
@cindex downward funargs
@cindex thunks
A @dfn{nested function} is a function defined inside another function.
(Nested functions are not supported for GNU C++.) The nested function's
name is local to the block where it is defined. For example, here we
define a nested function named @code{square}, and call it twice:
@example
@group
foo (double a, double b)
@{
double square (double z) @{ return z * z; @}
return square (a) + square (b);
@}
@end group
@end example
The nested function can access all the variables of the containing
function that are visible at the point of its definition. This is
called @dfn{lexical scoping}. For example, here we show a nested
function which uses an inherited variable named @code{offset}:
@example
bar (int *array, int offset, int size)
@{
int access (int *array, int index)
@{ return array[index + offset]; @}
int i;
@dots{}
for (i = 0; i < size; i++)
@dots{} access (array, i) @dots{}
@}
@end example
Nested function definitions are permitted within functions in the places
where variable definitions are allowed; that is, in any block, before
the first statement in the block.
It is possible to call the nested function from outside the scope of its
name by storing its address or passing the address to another function:
@example
hack (int *array, int size)
@{
void store (int index, int value)
@{ array[index] = value; @}
intermediate (store, size);
@}
@end example
Here, 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 the
containing function has exited, all hell will break loose. If you try
to call it after a containing scope level has exited, and if it refers
to 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 function
does not refer to anything that has gone out of scope, you should be
safe.
GNU CC implements taking the address of a nested function using a
technique called @dfn{trampolines}. A paper describing them is
available as @uref{http://people.debian.org/~karlheg/Usenix88-lexic.pdf}.
A nested function can jump to a label inherited from a containing
function, provided the label was explicitly declared in the containing
function (@pxref{Local Labels}). Such a jump returns instantly to the
containing function, exiting the nested function which did the
@code{goto} and any intermediate functions as well. Here is an example:
@example
@group
bar (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;
@dots{}
for (i = 0; i < size; i++)
@dots{} access (array, i) @dots{}
@dots{}
return 0;
/* @r{Control comes here from @code{access}
if it detects an error.} */
failure:
return -1;
@}
@end group
@end example
A nested function always has internal linkage. Declaring one with
@code{extern} is erroneous. If you need to declare the nested function
before its definition, use @code{auto} (which is otherwise meaningless
for function declarations).
@example
bar (int *array, int offset, int size)
@{
__label__ failure;
auto int access (int *, int);
@dots{}
int access (int *array, int index)
@{
if (index > size)
goto failure;
return array[index + offset];
@}
@dots{}
@}
@end example
@node Constructing Calls
@section Constructing Function Calls
@cindex constructing calls
@cindex forwarding calls
Using the built-in functions described below, you can record
the arguments a function received, and call another function
with the same arguments, without knowing the number or types
of the arguments.
You can also record the return value of that function call,
and later return that value, without knowing what data type
the function tried to return (as long as your caller expects
that data type).
@deftypefn {Built-in Function} {void *} __builtin_apply_args ()
This built-in function returns a pointer to data
describing how to perform a call with the same arguments as were passed
to 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 function
into a block of memory allocated on the stack. Then it returns the
address 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 size
of the stack argument data, in bytes.
This function returns a pointer to data describing
how to return whatever value was returned by @var{function}. The data
is saved in a block of memory allocated on the stack.
It is not always simple to compute the proper value for @var{size}. The
value is used by @code{__builtin_apply} to compute the amount of data
that should be pushed on the stack and copied from the incoming argument
area.
@end deftypefn
@deftypefn {Built-in Function} {void} __builtin_return (void *@var{result})
This built-in function returns the value described by @var{result} from
the containing function. You should specify, for @var{result}, a value
returned by @code{__builtin_apply}.
@end deftypefn
@node Naming Types
@section Naming an Expression's Type
@cindex naming types
You can give a name to the type of an expression using a @code{typedef}
declaration with an initializer. Here is how to define @var{name} as a
type name for the type of @var{exp}:
@example
typedef @var{name} = @var{exp};
@end example
This is useful in conjunction with the statements-within-expressions
feature. Here is how the two together can be used to define a safe
``maximum'' macro that operates on any arithmetic type:
@example
#define max(a,b) \
(@{typedef _ta = (a), _tb = (b); \
_ta _a = (a); _tb _b = (b); \
_a > _b ? _a : _b; @})
@end example
@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 in
The reason for using names that start with underscores for the local
variables is to avoid conflicts with variable names that occur within the
expressions that are substituted for @code{a} and @code{b}. Eventually we
hope to design a new form of declaration syntax that allows you to declare
variables whose scopes start only after their initializers; this will be a
more reliable way to prevent such conflicts.
@node Typeof
@section Referring to a Type with @code{typeof}
@findex typeof
@findex sizeof
@cindex macros, types of arguments
Another 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 the
construct acts semantically like a type name defined with @code{typedef}.
There are two ways of writing the argument to @code{typeof}: with an
expression or with a type. Here is an example with an expression:
@example
typeof (x[0](1))
@end example
@noindent
This 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:
@example
typeof (int *)
@end example
@noindent
Here the type described is that of pointers to @code{int}.
If you are writing a header file that must work when included in ISO C
programs, write @code{__typeof__} instead of @code{typeof}.
@xref{Alternate Keywords}.
A @code{typeof}-construct can be used anywhere a typedef name could be
used. For example, you can use it in a declaration, in a cast, or inside
of @code{sizeof} or @code{typeof}.
@itemize @bullet
@item
This declares @code{y} with the type of what @code{x} points to.
@example
typeof (*x) y;
@end example
@item
This declares @code{y} as an array of such values.
@example
typeof (*x) y[4];
@end example
@item
This declares @code{y} as an array of pointers to characters:
@example
typeof (typeof (char *)[4]) y;
@end example
@noindent
It is equivalent to the following traditional C declaration:
@example
char *y[4];
@end example
To see the meaning of the declaration using @code{typeof}, and why it
might be a useful way to write, let's rewrite it with these macros:
@example
#define pointer(T) typeof(T *)
#define array(T, N) typeof(T [N])
@end example
@noindent
Now the declaration can be rewritten this way:
@example
array (pointer (char), 4) y;
@end example
@noindent
Thus, @code{array (pointer (char), 4)} is the type of arrays of 4
pointers to @code{char}.
@end itemize
@node Lvalues
@section Generalized Lvalues
@cindex compound expressions as lvalues
@cindex expressions, compound, as lvalues
@cindex conditional expressions as lvalues
@cindex expressions, conditional, as lvalues
@cindex casts as lvalues
@cindex generalized lvalues
@cindex lvalues, generalized
@cindex extensions, @code{?:}
@cindex @code{?:} extensions
Compound expressions, conditional expressions and casts are allowed as
lvalues provided their operands are lvalues. This means that you can take
their addresses or store values into them.
Standard C++ allows compound expressions and conditional expressions as
lvalues, and permits casts to reference type, so use of this extension
is deprecated for C++ code.
For example, a compound expression can be assigned, provided the last
expression in the sequence is an lvalue. These two expressions are
equivalent:
@example
(a, b) += 5
a, (b += 5)
@end example
Similarly, the address of the compound expression can be taken. These two
expressions are equivalent:
@example
&(a, b)
a, &b
@end example
A conditional expression is a valid lvalue if its type is not void and the
true and false branches are both valid lvalues. For example, these two
expressions are equivalent:
@example
(a ? b : c) = 5
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -