动态跳转到C中的标签

cee*_*dee 6 c

我想显示输出 - 数字1到5,然后是无限的4-5.有什么方法可以传递i(4)的值而不是goto1中的字符i.或者是否有任何其他有效的方法来实现这一点,而没有说明开关中的所有选项(即案例1:goto1(c1)等...).

主要目的是跳转到在程序中计算其标签的语句.

#define goto1(i) \
goto c##i

int main(){    
    c1 : printf(" num is 1 \n");
    c2 : printf(" num is 2 \n");
    c3 : printf(" num is 3 \n");
    c4 : printf(" num is 4 \n");
    c5 : printf(" num is 5 \n");

    int i=4;
    goto1(i);
}
Run Code Online (Sandbox Code Playgroud)

Jon*_*ler 10

如果你......冒险(或者我的意思是愚蠢?),你可以使用GCC扩展标签作为值.

6.3标签作为价值观

您可以使用一元运算符' &&' 获取当前函数(或包含函数)中定义的标签的地址.值有类型void *.此值是常量,可以在该类型的常量有效的任何位置使用.例如:

 void *ptr;
 /* ... */
 ptr = &&foo;
Run Code Online (Sandbox Code Playgroud)

要使用这些值,您需要能够跳转到一个值.这是通过计算goto语句1,goto *exp;.例如,

 goto *ptr;
Run Code Online (Sandbox Code Playgroud)

void *允许任何类型的表达式.

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

 static void *array[] = { &&foo, &&bar, &&hack };
Run Code Online (Sandbox Code Playgroud)

然后您可以选择带索引的标签,如下所示:

 goto *array[i];
Run Code Online (Sandbox Code Playgroud)

请注意,这不会检查下标是否在C中的边界数组索引中从不这样做.

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

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

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

编写上述示例的另一种方法是

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

这对于生活在共享库中的代码更加友好,因为它减少了所需的动态重定位的数量,因此,允许数据是只读的.

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


脚注

[1] Fortran中的类似功能称为指定goto,但该名称在C中似乎不合适,其中人们可以做的不仅仅是在标签变量中存储标签地址.

在任何情况下都不应将此视为使用该功能的建议.计算goto最终从Fortran中删除; 它最好留在历史的垃圾箱里.


max*_*oom 5

你在要求跳桌吗?如果你正在使用gcc:它有一个跳转表机制.

#include <stdio.h>

int main()
{
    unsigned char data[] = { 1,2,3,4,5,4,5,0 };
    // data to "iterate" over, must be 0-terminated in this example

    void *jump_table[] = { &&L00, &&L01, &&L02, &&L03, &&L04, &&L05 };
    // you should fill this with all 256 possible values when using bytes as p-code

    unsigned char *p = data;

    begin:
        goto *jump_table[ *p ];

    L00:
        return 0; // end app
    L01:
        printf("num %i\n", (int)*p);
        goto next;
    L02:
        printf("num %i\n", (int)*p);
        goto next;
    L03:
        printf("num %i\n", (int)*p);
        goto next;
    L04:
        printf("num %i\n", (int)*p);
        goto next;
    L05:
        printf("num %i\n", (int)*p);
        goto next;
    L06:
    L07:
    // ...
    LFF:
        goto next;

    next:
        ++p;            // advance the data pointer to the next byte
        goto begin;     // start over

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

关于这种方法的专家是你省去了大的switch语句.