gcc: Labels as Values

1 
1 6.3 Labels as Values
1 ====================
1 
1 You can get the address of a label defined in the current function (or a
1 containing function) with the unary operator '&&'.  The value has type
1 'void *'.  This value is a constant and can be used wherever a constant
1 of that type is valid.  For example:
1 
1      void *ptr;
1      /* ... */
1      ptr = &&foo;
1 
1  To use these values, you need to be able to jump to one.  This is done
1 with the computed goto statement(1), 'goto *EXP;'.  For example,
1 
1      goto *ptr;
1 
1 Any expression of type 'void *' is allowed.
1 
1  One way of using these constants is in initializing a static array that
1 serves as a jump table:
1 
1      static void *array[] = { &&foo, &&bar, &&hack };
1 
1 Then you can select a label with indexing, like this:
1 
1      goto *array[i];
1 
1 Note that this does not check whether the subscript is in bounds--array
1 indexing in C never does that.
1 
1  Such an array of label values serves a purpose much like that of the
1 'switch' statement.  The 'switch' statement is cleaner, so use that
1 rather than an array unless the problem does not fit a 'switch'
1 statement very well.
1 
1  Another use of label values is in an interpreter for threaded code.
1 The labels within the interpreter function can be stored in the threaded
1 code for super-fast dispatching.
1 
1  You may not use this mechanism to jump to code in a different function.
1 If you do that, totally unpredictable things happen.  The best way to
1 avoid this is to store the label address only in automatic variables and
1 never pass it as an argument.
1 
1  An alternate way to write the above example is
1 
1      static const int array[] = { &&foo - &&foo, &&bar - &&foo,
1                                   &&hack - &&foo };
1      goto *(&&foo + array[i]);
1 
1 This is more friendly to code living in shared libraries, as it reduces
1 the number of dynamic relocations that are needed, and by consequence,
1 allows the data to be read-only.  This alternative with label
1 differences is not supported for the AVR target, please use the first
1 approach for AVR programs.
1 
1  The '&&foo' expressions for the same label might have different values
1 if the containing function is inlined or cloned.  If a program relies on
1 them being always the same, '__attribute__((__noinline__,__noclone__))'
1 should be used to prevent inlining and cloning.  If '&&foo' is used in a
1 static variable initializer, inlining and cloning is forbidden.
1 
1    ---------- Footnotes ----------
1 
1    (1) The analogous feature in Fortran is called an assigned goto, but
1 that name seems inappropriate in C, where one can do more than simply
1 store label addresses in label variables.
1