Dynamic jumps in C
What are dynamic jumps?
Have you ever wanted to dynamically decide where your program jumps to while it is already running?
In C you normally use things like if, switch, goto, and loops. But GCC and Clang also support something much more unusual: computed gotos.
With computed gotos, we can take the address of a label, store it in a variable, and later jump to that address.
Getting the Address of a Label
Normally, goto works like this:
1
2
3
4
goto loop_one;
loop_one:
// code
But GCC and Clang let us get the address of a label using &&:
1
2
3
4
void* loop_exec = &&loop_one;
loop_one:
// code
Now loop_exec contains the address of loop_one.
We can execute the jump dynamically using:
1
goto *loop_exec;
Changing the Jump While Running
This becomes interesting when we change the jump target during execution.
For example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
void* loop_exec = &&loop_one;
loop_one:
if (x) {
check_something();
} else {
loop_exec = &&loop_two;
}
goto loop_two;
loop_two:
do_something();
goto *loop_exec;
At the beginning:
The program starts at loop_one.
If x is true, loop_exec is never changed:
1
loop_one -> loop_two -> loop_one -> loop_two
But if x becomes false:
we change the destination:
Now the execution becomes:
1
loop_one -> loop_two -> loop_two -> loop_two
This Isn’t Standard C
This:
1
&&label
and:
1
goto *pointer;
are compiler extensions, not part of ISO C.