C 编译器可识别称为计算转移 (computed goto) 语句的 C 扩展。使用计算转移 (computed goto) 语句能够在运行时确定分支目标。通过使用 '&&' 运算符可以获取标签的地址,并且可以将标签地址指定给 void * 类型的指针:
void *ptr; ... ptr = &&label1;
后面的 goto 语句可以通过 ptr 转到 label1:
goto *ptr;
由于 ptr 在运行时进行计算,因此 ptr 可以接受作用域内任何标签的地址,而 goto 语句可以转到该位置。
使用计算转移 (computed goto) 语句的一种方法是用于转移表的实现:
static void *ptrarray[] = { &&label1, &&label2, &&label3 };
现在可以通过索引来选择数组元素:
goto *ptrarray[i];
标签的地址只能通过当前函数作用域计算。尝试在当前函数外部获取标签的地址会产生不可预测的结果。
转移表和开关语句的作用相似,但转移表使跟踪程序流更加困难。明显的差别是,开关语句转移目标都在 switch 保留字的正向。使用计算转移 (computed goto) 实现转移表可在正向和反向启用分支。
#include <stdio.h>
void foo()
{
void *ptr;
ptr = &&label1;
goto *ptr;
printf("Failed!\n");
return;
label1:
printf("Passed!\n");
return;
}
int main(void)
{
void *ptr;
ptr = &&label1;
goto *ptr;
printf("Failed!\n");
return 0;
label1:
foo();
return 0;
}
以下示例也使用转移表控制程序流:
#include <stdio.h>
int main(void)
{
int i = 0;
static void * ptr[3]={&&label1, &&label2, &&label3};
goto *ptr[i];
label1:
printf("label1\n");
return 0;
label2:
printf("label2\n");
return 0;
label3:
printf("label3\n");
return 0;
}
%example: a.out
%example: label1
计算转移 (computed goto) 语句的另一个应用是作为线程代码的解释程序。解释程序函数内部的标签地址可以存储在线程代码中以便快速分发。