首页 > 解决方案 > 在函数外访问标签地址

问题描述

我正在使用计算的 goto 编写“线程解释器”。如何初始化地址查找表,使其在不同功能中可见,而无需额外的运行时成本?

标签地址仅在同一函数中可见,静态查找表由编译器在数据部分初始化,每次调用时都没有运行时成本。但它只在同一个函数中可见,我希望有另一个函数可以访问它,例如缓存地址并在主解释器代码中保存查找。我可以将指针指向该表并将其存储在某个地方,但是每次调用函数时都会发生这种情况,并且会经常调用它。是的,这只是一个 mov,但还有其他方法吗?

#include <stdio.h>

static void** table_ptr;

// how do i declare static variable and init it later once?


// Tried this. Generates runtime assigns at each call. Not unexpected
// static void** jumps_addr;

int main()
{
    // labels are visible only inside the function
    
    // generates runtime assigns at each call
    // jumps_addr = (void* [10]){

    // this initializes it in static data section, but name is only visible inside this function
    static void* jumps_addr[10] = {
      [1] =  &&operation_print,
        
    };


    // want another way instead of this
    table_ptr = jumps_addr;

    // not optimize this 
    volatile int opcode = 1;

    goto *jumps_addr[opcode];
    
    return 0;
    
    operation_print:;
        printf("hello\n");
        
    return 0;
}


void do_some_preprocessing_work(void){
    
    // want access to jumps_addr table here
    // without having to store it somewhere
    
    // [do something with table_ptr]

    // this is to prevent optimization to explore what compiler does on godbolt.org
    // because it will optimize away table_ptr entirely if not used
    volatile i = 1;
    i += table_ptr[i];
    
    //actual code here will store labbel addrs into opcode struct to save table lookup at runtime
    
}

标签: c

解决方案


该解决方案可能听起来不正统,但是不使用任何功能,而只使用goto怎么样。

像这样:

#include <stdio.h>

int main()
{
    volatile int opcode;

    static void* jumps_addr[10] = {
        [0] = &&do_some_preprocessing_work,
        [1] = &&operation_print
    };
    
    opcode = 0;
    goto *jumps_addr[opcode];
    
    return 1;
    
    
    
    operation_print:
    
    printf("hello\n");
        
    return 0;
    
    
    
    do_some_preprocessing_work:
    
    printf("jumps_addr[%i]\n", ++opcode);
    goto *jumps_addr[opcode];
    
    return 1;
}

推荐阅读