gcc: Nested Functions
1
1 6.4 Nested Functions
1 ====================
1
1 A "nested function" is a function defined inside another function.
1 Nested functions are supported as an extension in GNU C, but are not
1 supported by GNU C++.
1
1 The nested function's name is local to the block where it is defined.
1 For example, here we define a nested function named 'square', and call
1 it twice:
1
1 foo (double a, double b)
1 {
1 double square (double z) { return z * z; }
1
1 return square (a) + square (b);
1 }
1
1 The nested function can access all the variables of the containing
1 function that are visible at the point of its definition. This is
1 called "lexical scoping". For example, here we show a nested function
1 which uses an inherited variable named 'offset':
1
1 bar (int *array, int offset, int size)
1 {
1 int access (int *array, int index)
1 { return array[index + offset]; }
1 int i;
1 /* ... */
1 for (i = 0; i < size; i++)
1 /* ... */ access (array, i) /* ... */
1 }
1
1 Nested function definitions are permitted within functions in the
1 places where variable definitions are allowed; that is, in any block,
1 mixed with the other declarations and statements in the block.
1
1 It is possible to call the nested function from outside the scope of
1 its name by storing its address or passing the address to another
1 function:
1
1 hack (int *array, int size)
1 {
1 void store (int index, int value)
1 { array[index] = value; }
1
1 intermediate (store, size);
1 }
1
1 Here, the function 'intermediate' receives the address of 'store' as an
1 argument. If 'intermediate' calls 'store', the arguments given to
1 'store' are used to store into 'array'. But this technique works only
1 so long as the containing function ('hack', in this example) does not
1 exit.
1
1 If you try to call the nested function through its address after the
1 containing function exits, all hell breaks loose. If you try to call it
1 after a containing scope level exits, and if it refers to some of the
1 variables that are no longer in scope, you may be lucky, but it's not
1 wise to take the risk. If, however, the nested function does not refer
1 to anything that has gone out of scope, you should be safe.
1
1 GCC implements taking the address of a nested function using a
1 technique called "trampolines". This technique was described in
1 'Lexical Closures for C++' (Thomas M. Breuel, USENIX C++ Conference
1 Proceedings, October 17-21, 1988).
1
1 A nested function can jump to a label inherited from a containing
1 function, provided the label is explicitly declared in the containing
1 function (⇒Local Labels). Such a jump returns instantly to the
1 containing function, exiting the nested function that did the 'goto' and
1 any intermediate functions as well. Here is an example:
1
1 bar (int *array, int offset, int size)
1 {
1 __label__ failure;
1 int access (int *array, int index)
1 {
1 if (index > size)
1 goto failure;
1 return array[index + offset];
1 }
1 int i;
1 /* ... */
1 for (i = 0; i < size; i++)
1 /* ... */ access (array, i) /* ... */
1 /* ... */
1 return 0;
1
1 /* Control comes here from 'access'
1 if it detects an error. */
1 failure:
1 return -1;
1 }
1
1 A nested function always has no linkage. Declaring one with 'extern'
1 or 'static' is erroneous. If you need to declare the nested function
1 before its definition, use 'auto' (which is otherwise meaningless for
1 function declarations).
1
1 bar (int *array, int offset, int size)
1 {
1 __label__ failure;
1 auto int access (int *, int);
1 /* ... */
1 int access (int *array, int index)
1 {
1 if (index > size)
1 goto failure;
1 return array[index + offset];
1 }
1 /* ... */
1 }
1