【GNU笔记】【C扩展系列】标签作为值

【GNU笔记】【C扩展系列】标签作为值 Labels as Values

标签作为值 Labels as Values

你可以使用一元运算符“&&”获取当前函数(或包含函数)中定义的标签的地址。值的类型为void *。这个值是一个常量,可以在该类型的常量有效的任何地方使用。例如:

void *ptr;
/* … */
ptr = &&foo;

要使用这些值,你需要能够跳转到一个值。这可以通过计算goto(computed goto)语句1goto *exp;来实现。比如说。

goto *ptr;

允许使用void*类型的任何表达式。

使用这些常量的一种方法是初始化用作跳转表的静态数组:

static void *array[] = { &&foo, &&bar, &&hack };

然后你可以选择一个带有索引的标签,像这样:

goto *array[i];

请注意,这并不检查下标是否在边界内–C语言中的数组索引从来不会这样做。

这种标签值数组的用途与switch语句的用途非常相似。switch语句更干净,所以使用它而不是数组,除非问题不适合switch语句。

标签值的另一个用途是用于线程代码的解释器中。解释器函数中的标签可以存储在线程代码中,以便进行超快速的调度。

你不能使用这种机制来跳转到不同函数中的代码。如果你这样做,会发生完全不可预测的事情。避免这种情况的最好方法是只将标签地址存储在自动变量中,而绝不将其作为参数传递。

上述示例的另一种写法是

static const int array[] = { &&foo - &&foo, &&bar - &&foo,
                             &&hack - &&foo };
goto *(&&foo + array[i]);

这对共享库中的代码更友好,因为它减少了所需的动态重定位的数量,因此允许数据为只读。AVR 目标不支持这种带有标签差异的替代方法,请对 AVR 程序使用第一种方法。

如果包含函数是内联的(inlined)或克隆的(cloned),则同一标签的&&foo表达式可能具有不同的值。如果一个程序依赖于它们总是相同的,那么应该使用__attribute__((__noinline__,__noclone__))来防止内联和克隆。如果在静态变量初始值设定项中使用&&foo,则禁止内联和克隆。


脚注

[参考资料]

6.3 Labels as Values



  1. Fortran 中的类似功能称为分配的 goto(assigned goto),但该名称在C语言中似乎并不合适,在C语言中,人们可以做的不仅仅是将标签地址存储在标签变量中。 ↩︎

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值