Is it possible to store the address of a label in a variable and use goto to jump to it? Is it possible to store the address of a label in a variable and use goto to jump to it? c c

Is it possible to store the address of a label in a variable and use goto to jump to it?


The C and C++ standards do not support this feature. However, the GNU Compiler Collection (GCC) includes a non-standard extension for doing this as described in this article. Essentially, they have added a special operator "&&" that reports the address of the label as type "void*". See the article for details.

P.S. In other words, just use "&&" instead of "&" in your example, and it will work on GCC.
P.P.S. I know you don't want me to say it, but I'll say it anyway,... DON'T DO THAT!!!


I know the feeling then everybody says it shouldn't be done; it just has to be done. In GNU C use &&the_label; to take the address of a label. (https://gcc.gnu.org/onlinedocs/gcc/Labels-as-Values.html) The syntax you guessed, goto *ptr on a void*, is actually what GNU C uses.

Or if you want to use inline assembly for some reason, here's how to do it with GNU C asm goto

// unsafe: this needs to use  asm goto so the compiler knows// execution might not come out the other side#define unsafe_jumpto(a) asm("jmp *%0"::"r"(a):)// target pointer, possible targets#define jumpto(a, ...) asm goto("jmp *%0" : : "r"(a) : : __VA_ARGS__)int main (void){  int i=1;  void* the_label_pointer;  the_label:  the_label_pointer = &&the_label;label2:  if( i-- )    jumpto(the_label_pointer, the_label, label2, label3);label3:  return 0;}

The list of labels must include every possible value for the_label_pointer.

The macro expansion will be something like

asm goto("jmp *%0" : : "ri"(the_label_pointer) : : the_label, label2, label3);

This compiles with gcc 4.5 and later, and with the latest clang which just got asm goto support some time after clang 8.0. https://godbolt.org/z/BzhckE. The resulting asm looks like this for GCC9.1, which optimized away the "loop" of i=i / i-- and just put the the_label after the jumpto. So it still runs exactly once, like in the C source.

# gcc9.1 -O3 -fpiemain:    leaq    .L2(%rip), %rax     # ptr = &&label    jmp *%rax                     # from inline asm.L2:    xorl    %eax, %eax          # return 0    ret

But clang didn't do that optimization and still has the loop:

# clang -O3 -fpiemain:    movl    $1, %eax    leaq    .Ltmp1(%rip), %rcx.Ltmp1:                                 # Block address taken    subl    $1, %eax    jb      .LBB0_4                  # jump over the JMP if i was < 1 (unsigned) before SUB.  i.e. skip the backwards jump if i wrapped    jmpq    *%rcx                   # from inline asm.LBB0_4:    xorl    %eax, %eax              # return 0    retq

The label address operator && will only work with gcc. And obviously the jumpto assembly macro needs to be implemented specifically for each processor (this one works with both 32 and 64 bit x86).

Also keep in mind that (without asm goto) there would be no guarantee that the state of the stack is the same at two different points in the same function. And at least with some optimization turned on it's possible that the compiler assumes some registers to contain some value at the point after the label. These kind of things can easily get screwed up then doing crazy shit the compiler doesn't expect. Be sure to proof read the compiled code.

These are why asm goto is necessary to make it safe by letting the compiler know where you will / might jump, getting consistent code-gen for the jump and the destination.


You can do something similar with setjmp/longjmp.

int main (void){    jmp_buf buf;    int i=1;    // this acts sort of like a dynamic label    setjmp(buf);    if( i-- )        // and this effectively does a goto to the dynamic label        longjmp(buf, 1);    return 0;}