gpt4 book ai didi

c - 为什么我们使用函数指针的结构?

转载 作者:行者123 更新时间:2023-12-03 23:39:15 25 4
gpt4 key购买 nike

关闭。这个问题是opinion-based .它目前不接受答案。












想改善这个问题吗?更新问题,以便可以通过 editing this post 用事实和引文回答问题.

7 个月前关闭。




Improve this question




正如他们所说,您从他人的代码中学习编码技术。我一直试图了解几个免费堆栈,它们都有一个共同点:函数指针的结构。我有以下与此架构相关的问题。

  • 这种架构背后有什么具体原因吗?
  • 通过函数指针调用函数是否有助于任何优化?

  • 示例:
    void do_Command1(void)
    {
    // Do something
    }

    void do_Command2(void)
    {
    // Do something
    }
    选项1:直接执行上述函数
    void do_Func(void)
    {
    do_Command1();
    do_Command2();
    }
    选项 2:通过函数指针间接执行上述函数
    // Create structure for function pointers
    typedef struct
    {
    void (*pDo_Command1)(void);
    void (*pDo_Command2)(void);
    }EXECUTE_FUNC_STRUCT;

    // Update structure instance with functions address
    EXECUTE_FUNC_STRUCT ExecFunc = {
    do_Command1,
    do_Command2,
    };


    void do_Func(void)
    {
    EXECUTE_FUNC_STRUCT *pExecFunc; // Create structure pointer

    pExecFun = &ExecFunc; // Assign structure instance address to the structure pointer

    pExecFun->pDo_Command1(); // Execute command 1 function via structure pointer
    pExecFun->pDo_Command2(); // Execute command 2 function via structure pointer
    }
    虽然选项 1 易于理解和实现,但为什么我们需要使用选项 2?

    最佳答案

    While Option 1 is easy to understand and implement, why do we need to use Option 2?


    选项 1 不允许您在不更改代码的情况下更改行为 - 每次执行程序时,它始终会以相同的顺序执行相同的功能。有时,这是正确的答案。
    选项 2 使您可以灵活地执行不同的功能,或执行 do_Command2之前 do_Command1 , 基于运行时的决策(比如在读取配置文件之后,或基于另一个操作的结果等)。
    来自个人经验的真实示例 - 我正在开发一个应用程序,该应用程序可以读取从 Labview 驱动的仪器生成的数据文件并将它们加载到数据库中。有四种不同的仪器,每种仪器有两种类型的文件,一种用于校准,另一种包含实际数据。文件命名约定是这样的,我可以根据文件名选择解析例程。现在,我可以编写我的代码,这样:
    void parse ( const char *fileName )
    {
    if ( fileTypeIs( fileName, "GRA" ) && fileExtIs( fileName, "DAT" ) )
    parseGraDat( fileName );
    else if ( fileTypeIs( fileName, "GRA" ) && fileExtIs ( fileName, "CAL" ) )
    parseGraCal( fileName );
    else if ( fileTypeIs( fileName, "SON" ) && fileExtIs ( fileName, "DAT" ) )
    parseSonDat( fileName );
    // etc.
    }
    那会很好用。但是,当时有可能会在以后添加新乐器,并且乐器可能会有其他文件类型。所以,我决定不使用长的 if-else 链,而是使用查找表。这样,如果我确实必须添加新的解析例程,我所要做的就是编写新例程并将其添加到查找表中 - 我不必修改任何主程序逻辑。 table 看起来像这样:
    struct lut {
    const char *type;
    const char *ext;
    void (*parseFunc)( const char * );
    } LUT[] = { {"GRA", "DAT", parseGraDat },
    {"GRA", "CAL", parseGraCal },
    {"SON", "DAT", parseSonDat },
    {"SON", "CAL", parseSonCal },
    // etc.
    };
    然后我有一个函数可以获取文件名,搜索查找表,并返回适当的解析函数(如果无法识别文件名,则返回 NULL):
    void (*parse)(const char *) = findParseFunc( LUT, fileName );
    if ( parse )
    parse( fileName );
    else
    log( ERROR, "No parsing function for %s", fileName );
    同样,我没有理由不能使用 if-else 链,回想起来,这可能是我应该为那个特定的 app1 做的事情。但它是一种非常强大的技术,可用于编写需要灵活且响应迅速的代码。
  • 我有过早泛化的倾向——我正在编写代码来解决我认为五年后会出现的问题,而不是今天的问题,我最终得到的代码往往比必要的更复杂。
  • 关于c - 为什么我们使用函数指针的结构?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66963032/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com