zoukankan      html  css  js  c++  java
  • 解释器中对 标号 的使用

    android_6200/dalvik/vm/mterp/out/InterpC-portdbg.c  + 467

    c89也支持

    向我这样看待码永远都学不好程序,感觉好迷茫,谁么时候能有个整体的认识?!

    写个示意程序:

          1 #include <stdio.h>                                                                                                                                                           
          2 #include <stdlib.h>
          3
          4 #define H(_op)  &&op_##_op
          5 #define HANDLE_OPCODE(_op) op_##_op:
          6
          7 #define DEFINE_GOTO_TABLE(_name) \
          8     static const void * _name[8] = {    \
          9         H(OP_NOP),                      \
         10         H(OP_MOVE),                     \
         11         H(OP_MOVE_16),                  \
         12         H(OP_MOVE_WIDE),                \
         13         H(OP_MOVE_OBJECT),              \
         14         H(OP_RETURN_WIDE),              \
         15         H(OP_CONST_4),                  \
         16         H(OP_CONST)                     \
         17     }
         18
         19 int main(void)
         20 {
         21     DEFINE_GOTO_TABLE(handlerTable);
         22
         23     goto *handlerTable[7];
         24
         25
         26 HANDLE_OPCODE(OP_NOP)
         27     printf("OP_NOP\n");
         28     exit(1);
         29 HANDLE_OPCODE(OP_MOVE)
         30     printf("OP_MOVE\n");
         31     exit(1);
         32 HANDLE_OPCODE(OP_MOVE_16)
         33     printf("OP_MOVE_16\n");
         34     exit(1);
         35 HANDLE_OPCODE(OP_MOVE_WIDE)
         36     printf("OP_MOVE_WIDE\n");
         37     exit(1);
         38 HANDLE_OPCODE(OP_MOVE_OBJECT)
         39     printf("OP_MOVE_OBJECT\n");
         40     exit(1);
         41 HANDLE_OPCODE(OP_RETURN_WIDE)
         42     printf("OP_RETURN_WIDE\n");
         43     exit(1);
         44 HANDLE_OPCODE(OP_CONST_4)
         45     printf("OP_CONST_4\n");
         46     exit(1);
         47 HANDLE_OPCODE(OP_CONST)
         48     printf("OP_CONST\n");
         49     exit(1);
         50
         51
         52     return 0;
         53 }

    参见:http://gcc.gnu.org/onlinedocs/gcc-3.2/gcc/Labels-as-Values.html#fn-1

    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 statement, 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 will serve 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.

    相比较于switch语句:

    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.

    dalvik虚拟机中如上,使用了该方法。

    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 will 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.

    看看宏定义中的局部标号:

    Locally Declared Labels

    Each statement expression is a scope in which local labels can be declared. A local label is simply an identifier; you can jump to it with an ordinary goto statement, but only from within the statement expression it belongs to.

    A local label declaration looks like this:

         __label__ label;
         

    or

         __label__ label1, label2, ...;
         

    Local label declarations must come at the beginning of the statement expression, right after the ({, before any ordinary declarations.

    The label declaration defines the label name, but does not define the label itself. You must do this in the usual way, with label:, within the statements of the statement expression.

    The local label feature is useful because statement expressions are often used in macros. If the macro contains nested loops, a goto can be useful for breaking out of them. However, an ordinary label whose scope is the whole function cannot be used: if the macro can be expanded several times in one function, the label will be multiply defined in that function. A local label avoids this problem. For example:

         #define SEARCH(array, target)                     \
         ({                                                \
           __label__ found;                                \
           typeof (target) _SEARCH_target = (target);      \
           typeof (*(array)) *_SEARCH_array = (array);     \
           int i, j;                                       \
           int value;                                      \
           for (i = 0; i < max; i++)                       \
             for (j = 0; j < max; j++)                     \
               if (_SEARCH_array[i][j] == _SEARCH_target)  \
                 { value = i; goto found; }                \
           value = -1;                                     \
          found:                                           \
           value;                                          \
         })
    
  • 相关阅读:
    silverlight 调用默认打印机
    拿来主意
    关于js智能提示的封装(修订版)
    silverlight 获取文本框焦点
    silverlight Timer
    winform 中写app.config文件时 调试情况下没有改变的原因
    关于asp:GridView和dx:ASPxGridView固定表头的jquery代码封装
    Microsoft Visual Studio 2010的前世今生
    游戏开发之我见
    JS中数组去重
  • 原文地址:https://www.cnblogs.com/openix/p/2818495.html
Copyright © 2011-2022 走看看