动态跳转到标签用C [英] Dynamic jump to label in C

查看:125
本文介绍了动态跳转到标签用C的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想以显示输出 - 数字1至5,接着4-5无限。有什么办法,我可以通过我(4)而不是在goto1字符i的值。或者是有实现这种无需说明如在开关的所有选项的任何其它有效的方法。(即壳体1:goto1(C1),等等。)

的主要目的是要跳转到的标签是在程序中计算出的声明。

 的#define goto1(我)\\
转到Ç##我诠释主(){
    C1:输出(num是1 \\ n);
    C2:输出(num是2 \\ n);
    C3:输出(num是3 \\ n);
    C4:输出(num是4 \\ n);
    C5:输出(num是5 \\ n);    INT I = 4;
    goto1(ⅰ);
}


解决方案

如果你是...冒险(或做我的意思是傻?),你可以使用GCC扩展的标签的值


  

6.3标号作为值


  
  

您可以在当前函数中定义的标号与一元运算符的地址(或包含函数)&放大器;&安培; 。值的类型为无效* 。这个值是一个常数并且可以使用,只要此种类型的恒定是有效的。例如:

 无效* PTR;
 / * ... * /
 PTR =放大器;&安培; foo的;

要使用这些值,需要能跳转到一个。 ;这是通过计算goto语句 1 转到* EXP完成。例如,

 转到* PTR;


  
  

键入无效* 的任何Ex pression是允许的。


  
  

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

 静态无效*数组[] = {&放大器;&安培;富,和放大器;&安培;酒吧,和放大器;&安培;劈};


  
  

然后你可以选择带有索引标签,如:

 转到*阵列[我]

请注意,这并不检查下标是否越界的数组索引用C从来没有做到这一点。


  
  

标签值的这种数组的用途很类似switch语句。 switch语句是更清洁,因此使用,而不是一个数组,除非这个问题不适合switch语句非常好。


  
  

标签值的另一个用途是在一个跨preTER螺纹code。跨preTER函数中的标签可以存储在线程code超快速调度。


  
  

您可以不使用这个机制跳转到code在不同的功能。如果你这样做,完全取消predictable的事情发生。为了避免这种情况的最好方法是存储在标签地址只在自动变量,从来没有把它作为一个参数。


  
  

写上面的例子中的另一种方法是

 静态const int的数组[] = {&放大器;&安培;富 - &功放;&安培;富,和放大器;&安培;酒吧 - &功放;&安培;富,
                              &功放;&安培;破解 - &功放;&安培;富};
 后藤*(&安培;&安培;富+阵列[我]);

这是在共享库中更友好的code生活,因为它减少了所需的动态重定位数量,因此,允许以只读的数据。


  
  

&放大器;&放大器;如果包含​​的内联函数或克隆了相同的标签富前pressions可能有不同的值。如果程序依赖于他们是始终不变的, __属性__((__ noinline__,__noclone __))应使用prevent内联和克隆。如果&放大器;&安培;富在一个静态变量初始化使用,内联和克隆是被禁止的。


  
  



  脚注


  
  

[1] Fortran中的类似功能称为指定的跳转,但这个名字在C,在那里人们可以做的不仅仅是存储标签地址多在标签变量似乎不妥。


在任何情况下本应被视为一项建议,使用该功能。该计算转到最终被删除的Fortran;它是在历史的垃圾堆最好留给。

I would like to display the output - numbers 1 to 5, followed by 4-5 infinitely. Is there any way i can pass the value of i(4) instead of the character i in goto1. Or is there any other efficient way of realizing this without illustrating all the options as in switch(i.e case 1: goto1(c1) ,etc..).

The main aim is to jump to a statement whose label is computed within the program.

#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);
}

解决方案

If you are ... adventurous (or do I mean silly?), you can use a GCC extension 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.

Under no circumstances should this be taken as a recommendation to use the feature. The computed goto was eventually removed from Fortran; it is best left in the dustbin of history.

这篇关于动态跳转到标签用C的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆