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