【问题标题】:how to write a function that links other functions in C [closed]如何编写一个链接C中其他函数的函数[关闭]
【发布时间】:2021-03-31 09:50:27
【问题描述】:

假设我有函数 A、B 和 C。

我想写一个函数,如下所示:

Linker(A,B,C,{{0,1,0},{0,0,1},{0,0,0}});

数组对应于第一个列表中的哪个元素将被调用。换句话说,当 A 完成时,它启动第二个元素 B,当 B 完成时,它调用第三个元素 C,当 C 完成时,什么都不调用。

然后链接器会展开到

generic preprocessing
run A
generic postprocessing

generic preprocessing
run B
generic postprocessing

generic preprocessing 
run C
generic postprocessing

我的想法是这样可以更容易地将函数链接在一起,并且可以节省我一些时间来编写预处理和后处理步骤。还有组织,防错,可理解性等......这个想法在C中可能吗?我需要使用 C++ 吗?我如何开始实施这样的想法?

我使用 stm32ide 作为我的编译器,因为此代码将在嵌入式设备上运行。

【问题讨论】:

  • C 和 C++ 是非常不同的语言。你用的是哪个?
  • 我会降低代码的可读性我认为这是一个 X-Y 问题。提高你想要实现的目标。
  • 这在 C 中是可能的,你需要使用函数指针。阅读更多:stackoverflow.com/questions/840501/…
  • 在 C 中,此类事情通常使用函数指针完成,而在 C++ 中,则使用 lambda 或 std::bind。
  • 如果这个{{0,1,0},{0,0,1},{0,0,0}}````the input to the functions? For example, {0, 1, 0}```是第一个函数的输入?

标签: c++ c linked-list clang stm32


【解决方案1】:

您可以通过设置一些“处理”类来存储指向您的函数的指针以及您希望在它们之间建立的链接来做到这一点:

class processor {
private:
    std::vector<void (*)()> funcs;
    std::vector<std::pair<int, int>> links;
public:
    void add_func(void (*func)()) { funcs.push_back(func); }
    void link(int from, int to) { links.push_back({from, to}); }
    void call(int indx) {
        // Make the call
        funcs.at(indx)();
 
        // Call any links
        for(auto it : links) {
            if(it.first == indx) { call(it.second); }
        }
    }
};

然后使用它,你只需要添加你的函数和链接,然后调用call():

int main() {
    processor p;
    p.add_func(A);
    p.add_func(B);
    p.add_func(C);
 
    p.link(0, 1); // A -> B
    p.link(1, 2); // B -> C
 
    p.call(0); // Call A
 
    return 0;
}

在此处查看实际操作:https://ideone.com/M1Qj6f

【讨论】:

    【解决方案2】:

    如果我理解正确,您希望将一个函数作为参数传递给另一个函数。

    对于c++,您可以使用函数指针。

    #include <iostream>
    
    void helloWorld()
    {
        std::cout << "Hello World" << std::endl;
    }
    
    
    int main()
    {
        helloWorld();
    
        # Here we get the memory adress of the function helloWorld.
        auto secondHelloWorld = &helloWorld;
    
        # Here, an implicit converstion is going on.
        auto thridHelloWorld = helloWorld;
    
        secondHelloWorld();
        thirdHelloWorld();
    
        std::cin.get();
    }
    

    如果你想更明确的类型,你可以写

    #include <iostream>
    
    void helloWorld()
    {
        std::cout << "Hello World" << std::endl;
    }
    
    
    int main()
    {
        helloWorld();
    
        void(*secondHelloWorld)() = helloWorld;
    
        void(*thridHelloWorld)() = helloWorld;
    
        secondHelloWorld();
        thirdHelloWorld();
    
        std::cin.get();
    }
    

    我无法帮助您如何准确地实现这一点。我需要知道你的要求。

    HTH

    【讨论】:

      【解决方案3】:

      您的问题应该得到澄清。如果我理解得很好,您想包装一个函数,就像在上下文管理器中所做的那样。你应该明确你的函数A、B、C的签名是什么以及必须如何使用{{0,1,0},{0,0,1},{0,0,0}}。

      所以为了简单起见,我假设这三个函数不带参数,也不返回任何内容。

      #include <stdio.h>
      
      void context_manager(
          void (*f)(),
          void (*enter)(),    
          void (*exit)()                                                       
      ) {   
          enter();        
          f();
          exit();
      }
      
      void my_enter() { printf("generic preprocessing\n"); }
      void my_exit() { printf("generic postprocessing\n\n"); }
      void a() { printf("run A\n"); }
      void b() { printf("run B\n"); }
      void c() { printf("run C\n"); }
      
      void linker(void **fs, unsigned n) {
          for (unsigned i = 0; i < n; i++) {
              context_manager(fs[i], my_enter, my_exit);
          }   
      }
      
      int main() { 
          void * fs[] = {a, b, c};
          linker(fs, sizeof(fs) / sizeof(void *));
          return 0;       
      }
      

      结果:

      generic preprocessing
      run A
      generic postprocessing
      
      generic preprocessing
      run B
      generic postprocessing
      
      generic preprocessing
      run C
      generic postprocessing
      

      您显然可以修改f 和linker 的签名来传递一些参数。

      【讨论】:

        【解决方案4】:

        难点在于:Linker(A,B,C,{{0,1,0},{0,0,1},{0,0,0}}); 不能用 C 编写。语言缺乏:

        • 函数自动处理或可变数量的参数:你必须给出数量的提示,函数必须猜测类型
        • 该语言中不存在文字多维数组。

        换句话说,我可以想象如何在 Python 中编写能够接受该语法(除了分号)的东西,但在 C 中却不行。构建一个能够处理一堆函数的事物根据 something 链接它们不是问题,可以在 C 中完成。但我无法猜测 something 应该是什么,以及您打算如何传递函数和something 到 thing,同时尊重 C 语法。

        【讨论】:

          【解决方案5】:

          假设我了解您的目的,并假设所有函数都具有相同的返回类型和参数列表,您可以设置一个函数指针数组和一个整数数组来指示从中执行哪个函数列表:

          void A(void) { puts( "In A" ); }
          void B(void) { puts( "In B" ); }
          void C(void) { puts( "In C" ); }
          
          /**
           * Call each of the functions in f based on the values in seq;
           * each seq[i] is treated as an index into f.
           *
           * A negative value in seq[i] indicates the end of the sequence.
           *
           * Inputs:
           *    f     - list of functions we want to execute
           *    seq   - specifies the order in which the functions are to be executed
           */
          void Linker( void (*f[])(void), int *seq )
          {
            for ( int i = 0; seq[i] >= 0; i++ )
            {
              f[seq[i]]();
            }
          }
          
          int main( void )
          {
            /**
             * Use compound literals to set up each array.
             */
            Linker( (void (*[])(void)) {A, B, C}, (int []) {0, 1, 2, 2, 1, 2, 0, 0, 0, -1} );
          }
          

          输出:

          In A
          In B
          In C
          In C
          In B
          In C
          In A
          In A
          In A
          

          如果函数具有不同的返回类型,或者它们具有相同的返回类型但采用不同的参数列表(甚至是具有不同值的相同参数列表),那么这将需要稍微充实一下。您可能需要创建一个“函子”的 C 等效项(基本上是一种抽象出函数返回类型和其他细节的结构类型)。但它应该会给你一些想法。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2019-04-26
            • 2023-01-30
            • 1970-01-01
            • 2020-07-25
            • 2021-07-30
            • 1970-01-01
            • 1970-01-01
            • 2021-05-09
            相关资源
            最近更新 更多