c - 动态跳转到 C 中的标签

标签 c

我想显示输出 - 数字 1 到 5,然后无限地显示 4-5。有什么办法可以传递 i(4) 的值而不是 goto1 中的字符 i。或者是否有任何其他有效的方法来实现这一点而无需像 switch 那样说明所有选项(即案例 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);
}

最佳答案

如果您...喜欢冒险(或者我的意思是愚蠢?),您可以使用 GCC 扩展 Labels as Values .

6.3 Labels as Values

You can get the address of a label defined in the current function (or a containing function) with the unary operator ‘&&’. The value has type void *. This value is a constant and can be used wherever a constant of that type is valid. For example:

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

To use these values, you need to be able to jump to one. This is done with the computed goto statement1, goto *exp;. For example,

 goto *ptr;

Any expression of type void * is allowed.

One way of using these constants is in initializing a static array that serves as a jump table:

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

Then you can select a label with indexing, like this:

 goto *array[i];

Note that this does not check whether the subscript is in bounds—array indexing in C never does that.

Such an array of label values serves a purpose much like that of the switch statement. The switch statement is cleaner, so use that rather than an array unless the problem does not fit a switch statement very well.

Another use of label values is in an interpreter for threaded code. The labels within the interpreter function can be stored in the threaded code for super-fast dispatching.

You may not use this mechanism to jump to code in a different function. If you do that, totally unpredictable things happen. The best way to avoid this is to store the label address only in automatic variables and never pass it as an argument.

An alternate way to write the above example is

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

This is more friendly to code living in shared libraries, as it reduces the number of dynamic relocations that are needed, and by consequence, allows the data to be read-only.

The &&foo expressions for the same label might have different values if the containing function is inlined or cloned. If a program relies on them being always the same, __attribute__((__noinline__, __noclone__)) should be used to prevent inlining and cloning. If &&foo is used in a static variable initializer, inlining and cloning is forbidden.


Footnotes

[1] The analogous feature in Fortran is called an assigned goto, but that name seems inappropriate in C, where one can do more than simply store label addresses in label variables.

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

关于c - 动态跳转到 C 中的标签,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15702297/

相关文章:

c++ - 如何在 Windows 中编译 nDPI 库自带的 ndpiReader.c?

c - 范围退出时未释放字符串数组

c - 我在 C/Linux 中实现 printf 函数

c - 释放双指针

c - printf 有符号整数和小数点,带负号的问题

c - 将 4x5 矩阵转置为 5x4 奇数输出

C 基本菜单驱动程序,无全局变量的气体计算器

c++ - 限制文件夹重命名 cocoa

c - 遍历C字符串: get the last word of a string

c - 程序因 free() 而崩溃