C语言中的跳转表数组

C语言中的跳转表数组,c,function-pointers,jump-table,C,Function Pointers,Jump Table,我正在尝试优化对我制作的一些跳转表的访问,它们如下所示: int (*const usart_ctrl_table[USART_READ_WRITE_CLEAR])() = {zg_usartCtrlRead, zg_usartCtrlWrite, zg_usartCtrlClr}; int (*const usart_frame_table[USART_READ_WRITE_CLEAR])() = {zg_usartFrameRead, zg_usartFrameWrite, zg_usar

我正在尝试优化对我制作的一些跳转表的访问,它们如下所示:

int (*const usart_ctrl_table[USART_READ_WRITE_CLEAR])() =
{zg_usartCtrlRead, zg_usartCtrlWrite, zg_usartCtrlClr};

int (*const usart_frame_table[USART_READ_WRITE_CLEAR])() =
{zg_usartFrameRead, zg_usartFrameWrite, zg_usartFrameClr};

int (*const usart_trig_ctrl_table[USART_READ_WRITE_CLEAR])() =
{zg_usartTrigctrlRead, zg_usartTrigctrlWrite, zg_usartTrigctrlClr};
如您所见,这些函数用于在硬件级别访问usart外围设备,并按读/写/清除顺序排列在表中

我试图做的是创建另一个包含跳转表的跳转表,通过这种方式,我可以在启动时初始化所有usart的寄存器,或者在需要时在以后更改单个寄存器

i、 e

正如您可能已经猜到的,我正在努力找出如何构造这个表。我想这是两件事之一:

  • 另一个简单的指针数组,因为即使跳转表本身也是指针数组。因此,我的初始化将是:

    const int* (*usart_peripheral_table[<number of jump tables])() = 
    {usart_ctrl_table, usart_frame_table, usart_trig_ctrl_table};
    

    上述两种方法都会产生错误“从不可映射指针类型初始化”,我尝试过的所有其他组合也会出现错误

    只需添加一个
    *
    ,就像您在定义数组时添加的
    []
    一样

    int zg_usartCtrlRead();
    int zg_usartCtrlWrite();
    int zg_usartCtrlClr();
    int zg_usartFrameRead();
    int zg_usartFrameWrite();
    int zg_usartFrameClr();
    int zg_usartTrigctrlRead();
    int zg_usartTrigctrlWrite();
    int zg_usartTrigctrlClr();
    
    int (*const usart_ctrl_table[])() =
    {zg_usartCtrlRead, zg_usartCtrlWrite, zg_usartCtrlClr};
    
    int (*const usart_frame_table[])() =
    {zg_usartFrameRead, zg_usartFrameWrite, zg_usartFrameClr};
    
    int (*const usart_trig_ctrl_table[])() =
    {zg_usartTrigctrlRead, zg_usartTrigctrlWrite, zg_usartTrigctrlClr};
    
    int (* const * const usart_peripheral_table[])() = 
    {usart_ctrl_table, usart_frame_table, usart_trig_ctrl_table};
    
    用法:

    usart_peripheral_table[1][2](5, 1, 3, 5, 6);
    
    顺便说一句,函数声明
    ()
    上的空参数列表表示未指定的参数数量和类型。如果不希望向函数传递任何参数,请执行
    (void)

    这:

    但您可能希望编写访问器函数,以返回指向函数数组的指针。再简单不过了

    #include <stddef.h>
    
    int (*usart_ctrl_table_get(size_t idx))() {
        return usart_ctrl_table[idx];
    }
    
    int (*usart_frame_table_get(size_t idx))() {
        return usart_frame_table[idx];
    }
    
    int (*usart_trig_ctrl_table_get(size_t idx))() {
        return usart_trig_ctrl_table[idx];
    }
    
    int (* const (* const usart_peripheral_table_indirect[])(size_t))() = {
        usart_ctrl_table_get, 
        usart_frame_table_get,
        usart_trig_ctrl_table_get,
    };
    

    只需添加一个
    *
    ,就像您在定义数组时添加的
    []
    一样

    int zg_usartCtrlRead();
    int zg_usartCtrlWrite();
    int zg_usartCtrlClr();
    int zg_usartFrameRead();
    int zg_usartFrameWrite();
    int zg_usartFrameClr();
    int zg_usartTrigctrlRead();
    int zg_usartTrigctrlWrite();
    int zg_usartTrigctrlClr();
    
    int (*const usart_ctrl_table[])() =
    {zg_usartCtrlRead, zg_usartCtrlWrite, zg_usartCtrlClr};
    
    int (*const usart_frame_table[])() =
    {zg_usartFrameRead, zg_usartFrameWrite, zg_usartFrameClr};
    
    int (*const usart_trig_ctrl_table[])() =
    {zg_usartTrigctrlRead, zg_usartTrigctrlWrite, zg_usartTrigctrlClr};
    
    int (* const * const usart_peripheral_table[])() = 
    {usart_ctrl_table, usart_frame_table, usart_trig_ctrl_table};
    
    用法:

    usart_peripheral_table[1][2](5, 1, 3, 5, 6);
    
    顺便说一句,函数声明
    ()
    上的空参数列表表示未指定的参数数量和类型。如果不希望向函数传递任何参数,请执行
    (void)

    这:

    但您可能希望编写访问器函数,以返回指向函数数组的指针。再简单不过了

    #include <stddef.h>
    
    int (*usart_ctrl_table_get(size_t idx))() {
        return usart_ctrl_table[idx];
    }
    
    int (*usart_frame_table_get(size_t idx))() {
        return usart_frame_table[idx];
    }
    
    int (*usart_trig_ctrl_table_get(size_t idx))() {
        return usart_trig_ctrl_table[idx];
    }
    
    int (* const (* const usart_peripheral_table_indirect[])(size_t))() = {
        usart_ctrl_table_get, 
        usart_frame_table_get,
        usart_trig_ctrl_table_get,
    };
    

    您可能会发现,为函数指针定义
    typedef
    ,可以使代码更易于阅读和维护(尽管我也看到有人建议不要这样做):


    您可能会发现,为函数指针定义
    typedef
    ,可以使代码更易于阅读和维护(尽管我也看到有人建议不要这样做):


    关于“什么是正确的方法”——你回答了你的问题。您需要多个并行表。那很好。因此,最好的方法可能是定义一个指针,该指针可以配置为在运行时指向这些表中的一个或另一个。问:当你尝试这种方法时,问题到底是什么?问:您能否显示相关代码和确切的错误消息(如果适用)?添加了错误编辑,请参阅“正确的方法是什么”-您回答了您的问题。您需要多个并行表。那很好。因此,最好的方法可能是定义一个指针,该指针可以配置为在运行时指向这些表中的一个或另一个。问:当你尝试这种方法时,问题到底是什么?问:您能否显示相关代码和确切的错误消息(如果适用)?添加了错误编辑您答案的第一部分似乎是正确的方法。然而,我感到困惑。为什么我需要添加第二个const关键字,为什么我不能在const前面添加另一个asterix运算符,即…(*const…)您能进一步解释一下为什么这也会创建一个2d数组,如您的“用法”示例所示吗?谢谢:)re:第二次编辑:哈哈哈。。。也许我想做一个指针表,指向指向另一个指针的指针,然后指向指向另一个指针的月亮!!在大多数上下文中,XDArrays“decay”或“shall”被转换(读作:magically convert)为指向数组第一个成员的指针。如果你真的不懂,就在网上找一些好文章。我的
    usart\u peripheral\u表
    是一个指向函数指针的指针数组,
    a[b]
    操作符等于
    *(a+b)
    其余部分来自指针算术(也是C中阅读的一个很好的主题)。yeh肯定理解衰变,这就是为什么我最初认为它是另一个简单的指针数组或指向指针的指针数组。。。很高兴我至少在这里走对了路。非常感谢你的回答,我会更仔细地研究它,并运用我学到的知识:)你回答的第一部分似乎是正确的方法。然而,我感到困惑。为什么我需要添加第二个const关键字,为什么我不能在const前面添加另一个asterix运算符,即…(*const…)您能进一步解释一下为什么这也会创建一个2d数组,如您的“用法”示例所示吗?谢谢:)re:第二次编辑:哈哈哈。。。也许我想做一个指针表,指向指向另一个指针的指针,然后指向指向另一个指针的月亮!!在大多数上下文中,XDArrays“decay”或“shall”被转换(读作:magically convert)为指向数组第一个成员的指针。如果你真的不懂,就在网上找一些好文章。我的
    usart\u peripheral\u表
    是一个指向函数指针的指针数组,
    a[b]
    操作符等于
    *(a+b)
    其余部分来自指针算术(也是C中阅读的一个很好的主题)。yeh肯定理解衰变,这就是为什么我最初认为它是另一个简单的指针数组或指向指针的指针数组。。。很高兴我至少在这里走对了路。非常感谢你的回答,我会更仔细地研究它,并应用我学到的知识:)当然同意,尽管我通常只是等到我真正了解我正在做的某个特定的实验之后再定义。。。只是为了确保在我玩弄想法的时候,所有的一切都在我面前。我当然同意,尽管我通常只是等到我真正了解我在做什么,然后再定义。。。只是为了确保在我玩弄创意的时候,一切都在我面前。
    usart_peripheral_table[1][2](5, 1, 3, 5, 6);
    
    const int* (*usart_peripheral_table[<number of jump tables])();
    
    const int** (*usart_peripheral_table[<number of jump tables])() 
    
    int (* const usart_peripheral_table_2d[][3])() = {
        {
            zg_usartCtrlRead, zg_usartCtrlWrite, zg_usartCtrlClr, 
        }, {
            zg_usartFrameRead, zg_usartFrameWrite, zg_usartFrameClr,
        }, {
            zg_usartTrigctrlRead, zg_usartTrigctrlWrite, zg_usartTrigctrlClr,
        },
    };
    
    #include <stddef.h>
    
    int (*usart_ctrl_table_get(size_t idx))() {
        return usart_ctrl_table[idx];
    }
    
    int (*usart_frame_table_get(size_t idx))() {
        return usart_frame_table[idx];
    }
    
    int (*usart_trig_ctrl_table_get(size_t idx))() {
        return usart_trig_ctrl_table[idx];
    }
    
    int (* const (* const usart_peripheral_table_indirect[])(size_t))() = {
        usart_ctrl_table_get, 
        usart_frame_table_get,
        usart_trig_ctrl_table_get,
    };
    
    int main() {
        usart_peripheral_table_indirect[2](1)();
    }
    
    #include <stdio.h>
    #include <stdlib.h>
    
    #define UART_RWC 3U
    
    typedef int (*uart_ctl_func)(void);
    
    int uart_read(void)
    {
      printf("Read.\n");
      fflush(stdout);
      return 0;
    }
    
    int uart_write(void)
    {
      printf("Write.\n");
      fflush(stdout);
      return(0);
    }
    
    int uart_clear(void)
    {
      printf("Clear.\n");
      fflush(stdout);
      return 0;
    }
    
    uart_ctl_func uart_ctl_jump_table[][UART_RWC] = {
      { uart_read, uart_write, uart_clear },
      { uart_read, uart_write, uart_clear }
    };
    
    int main(void)
    {
      uart_ctl_jump_table[0][1](); // Write.
      uart_ctl_jump_table[1][0](); // Read.
      uart_ctl_jump_table[1][2](); // Clear.
    
      return EXIT_SUCCESS;
    }
    
    #include <stdio.h>
    #include <stdlib.h>
    
    #define UART_RWC 3U
    
    typedef int (*uart_ctl_func)(void);
    
    int uart_read(void)
    {
      printf("Read.\n");
      fflush(stdout);
      return 0;
    }
    
    int uart_write(void)
    {
      printf("Write.\n");
      fflush(stdout);
      return(0);
    }
    
    int uart_clear(void)
    {
      printf("Clear.\n");
      fflush(stdout);
      return 0;
    }
    
    typedef struct {
      uart_ctl_func read;
      uart_ctl_func write;
      uart_ctl_func clear;
    } uart_ctl_set_t;
    
    typedef struct {
      uart_ctl_set_t ctrl;
      uart_ctl_set_t frame;
      uart_ctl_set_t trig;
    } uart_ctl_table_t;
    
    const uart_ctl_table_t uart_ctl_table = {
      .ctrl = { uart_read, uart_write, uart_clear },
      .frame = { uart_read, uart_write, uart_clear },
      .trig = { uart_read, uart_write, uart_clear }
    };
    
    int main(void)
    {
      uart_ctl_table.ctrl.write(); // Write.
      uart_ctl_table.frame.read(); // Read.
      uart_ctl_table.trig.clear(); // Clear.
    
      return EXIT_SUCCESS;
    }