📄 extend.texi
字号:
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:@example@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; @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 exampleA nested function always has internal linkage. Declaring one with@code{extern} is erroneous. If you need to declare the nested functionbefore its definition, use @code{auto} (which is otherwise meaninglessfor function declarations).@examplebar (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 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).@table @code@findex __builtin_apply_args@item __builtin_apply_args ()This built-in function returns a pointer of type @code{void *} 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.@findex __builtin_apply@item __builtin_apply (@var{function}, @var{arguments}, @var{size})This built-in function invokes @var{function} (type @code{void (*)()})with a copy of the parameters described by @var{arguments} (type@code{void *}) and @var{size} (type @code{int}).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 of type @code{void *} 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.@findex __builtin_return@item __builtin_return (@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 table@node Naming Types@section Naming an Expression's Type@cindex naming typesYou 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 atype name for the type of @var{exp}:@exampletypedef @var{name} = @var{exp};@end exampleThis is useful in conjunction with the statements-within-expressionsfeature. 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 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.@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:@exampletypeof (x[0](1))@end example@noindentThis assumes that @code{x} is an array of functions; the type describedis that of the values of the functions.Here is an example with a typename as the argument:@exampletypeof (int *)@end example@noindentHere the type described is that of pointers to @code{int}.If you are writing a header file that must work when included in ANSI 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}.@itemize @bullet@itemThis declares @code{y} with the type of what @code{x} points to.@exampletypeof (*x) y;@end example@itemThis declares @code{y} as an array of such values.@exampletypeof (*x) y[4];@end example@itemThis declares @code{y} as an array of pointers to characters:@exampletypeof (typeof (char *)[4]) y;@end example@noindentIt is equivalent to the following traditional C declaration:@examplechar *y[4];@end exampleTo see the meaning of the declaration using @code{typeof}, and why itmight 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@noindentNow the declaration can be rewritten this way:@examplearray (pointer (char), 4) y;@end example@noindentThus, @code{array (pointer (char), 4)} is the type of arrays of 4pointers 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{?:} extensionsCompound expressions, conditional expressions and casts are allowed aslvalues provided their operands are lvalues. This means that you can taketheir addresses or store values into them.Standard C++ allows compound expressions and conditional expressions aslvalues, and permits casts to reference type, so use of this extensionis deprecated for C++ code.For example, a compound expression can be assigned, provided the lastexpression in the sequence is an lvalue. These two expressions areequivalent:@example(a, b) += 5a, (b += 5)@end exampleSimilarly, the address of the compound expression can be taken. These twoexpressions are equivalent:@example&(a, b)a, &b@end exampleA conditional expression is a valid lvalue if its type is not void and thetrue and false branches are both valid lvalues. For example, these twoexpressions are equivalent:@example(a ? b : c) = 5(a ? b = 5 : (c = 5))@end exampleA cast is a valid lvalue if its operand is an lvalue. A simpleassignment whose left-hand side is a cast works by converting theright-hand side first to the specified type, then to the type of theinner left-hand side expression. After this is stored, the value isconverted back to the specified type to become the value of theassignment. Thus, if @code{a} has type @code{char *}, the following twoexpressions are equivalent:@example(int)a = 5(int)(a = (char *)(int)5)@end exampleAn assignment-with-arithmetic operation such as @samp{+=} applied to a castperforms the arithmetic using the type resulting from the cast, and thencontinues as in the previous case. Therefore, these two expressions areequivalent:@example(int)a += 5(int)(a = (char *)(int) ((int)a + 5))@end exampleYou cannot take the address of an lvalue cast, because the use of itsaddress would not work out coherently. Suppose that @code{&(int)f} werepermitted, where @code{f} has type @code{float}. Then the followingstatement would try to store an integer bit-pattern where a floatingpoint number belongs:@example*&(int)f = 1;@end exampleThis is quite different from what @code{(int)f = 1} would do---thatwould convert 1 to floating point and store it. Rather than cause thisinconsistency, we think it is better to prohibit use of @samp{&} on a cast.If you really do want an @code{int *} pointer with the address of@code{f}, you can simply write @code{(int *)&f}.@node Conditionals@section Conditionals with Omitted Operands@cindex conditional expressions, extensions@cindex omitted middle-operands@cindex middle-operands, omitted@cindex extensions, @code{?:}@cindex @code{?:} extensionsThe middle operand in a conditional expression may be omitted. Thenif the first operand is nonzero, its value is the value of the conditionalexpression.Therefore, the expression@examplex ? : y@end example@noindenthas the value of @code{x} if that is nonzero; otherwise, the value of@code{y}.This example is perfectly equivalent to@examplex ? x : y@end example@cindex side effect in ?:@cindex ?: side effect@noindentIn this simple case, the ability to omit the middle operand is notespecially useful. When it becomes useful is when the first operand does,or may (if it is a macro argument), contain a side effect. Then repeatingthe operand in the middle would perform the side effect twice. Omittingthe middle operand uses the value already computed without the undesirableeffects of recomputing it.@node Long Long@section Double-Word Integers@cindex @code{long long} data types@cindex double-word arithmetic@cindex multiprecision arithmeticGNU C supports data types for integers that are twice as long as@code{long int}. Simply write @code{long long int} for a signedinteger, or @code{unsigned long long int} for an unsigned integer.To make an integer constant of type @code{long long int}, add the suffix@code{LL} to the integer. To make an integer constant of type@code{unsigned long long int}, add the suffix @code{ULL} to the integer.You can use these types in arithmetic like any other integer types.Addition, subtraction, and bitwise boolean operations on these typesare open-coded on all types of machines. Multiplication is open-coded
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -