【问题标题】:How to define an array of functions in C如何在 C 中定义函数数组
【发布时间】:2011-03-15 09:37:20
【问题描述】:

我有一个包含如下声明的结构:

void (*functions[256])(void) //Array of 256 functions without arguments and return value

我想在另一个函数中定义它,但是有 256 个函数! 我可以这样做:

struct.functions[0] = function0;
struct.functions[1] = function1;
struct.functions[2] = function2;

等等,但这太累了,我的问题是有什么办法可以做这样的事情吗?

struct.functions = { function0, function1, function2, function3, ..., };

编辑:如 Chris Lutz 所说,已更正语法错误。

【问题讨论】:

    标签: c arrays function definition


    【解决方案1】:

    我有一个包含如下声明的结构:

    不,你没有。那是语法错误。您正在寻找:

    void (*functions[256])();
    

    这是一个函数指针数组。但是请注意,void func() 不是“不接受任何参数且不返回任何内容的函数”。它是一个接受未指定数量或类型的参数并且不返回任何内容的函数。如果你想要“没有参数”,你需要这个:

    void (*functions[256])(void);
    

    在 C++ 中,void func() 确实 的意思是“不接受任何参数”,这会引起一些混乱(尤其是因为 C 为 void func() 指定的功能具有可疑的价值。)

    无论哪种方式,你都应该typedef你的函数指针。它会让代码更容易理解,而且你只有一次机会(typedef)弄错语法:

    typedef void (*func_type)(void);
    // ...
    func_type functions[256];
    

    反正不能赋值给数组,但是可以初始化数组,复制数据:

    static func_type functions[256] = { /* initializer */ };
    memcpy(mystruct.functions, functions, sizeof(functions));
    

    【讨论】:

    • 请注意 memcpy() 是危险且不可移植的,因为结构可能包含任意数量的填充字节。如果您使用这里显示的 memcpy(),则必须验证编译器是否启用了填充。通常通过assert(sizeof(the_struct.functions) == sizeof(functions)) 或类似方式。
    • 这是不正确的。 sizeof(some_struct) 返回结构的大小 + 任何必要的填充。例如,请参阅this question。上面memcpy的用法是正确的。
    • ..在这种情况下,memcpy() 无论如何都没有用于结构 - 它用于从一个数组复制到另一个数组,大小相同,这很好。目标数组是结构成员这一事实并不重要。
    • 我可能应该注意到 struct 是一个关键字,因此即使对于永远不会接近编译器的示例代码,使用它作为变量名也是错误的。
    • func() 和 func(void) 之间的区别只是 C++ 的问题,而不是 C 的问题,是吗?
    【解决方案2】:

    我有同样的问题,这是我的小程序来测试解决方案。它看起来很简单,所以我想我会分享给未来的访客。

    #include <stdio.h>
    
    int add(int a, int b) {
        return a+b;
    }
    
    int minus(int a, int b) {
        return a-b;
    }
    
    int multiply(int a, int b) {
        return a*b;
    }
    
    typedef int (*f)(int, int);                 //declare typdef
    
    f func[3] = {&add, &minus, &multiply};      //make array func of type f,
                                                //the pointer to a function
    int main() {
        int i;
        for (i = 0; i < 3; ++i) printf("%d\n", func[i](5, 4));
        return 0;
    }
    

    【讨论】:

      【解决方案3】:

      你可以动态地做...这是一个用 malloc 分配的动态函数数组的小例子...

      #include <stdio.h>
      #include <stdlib.h>
      
      typedef void (*FOO_FUNC)(int x);
      
      void a(int x)
      {
          printf("Function a: %d\n", x);
      }
      
      void b(int x)
      {
          printf("Function b: %d\n", x);
      }
      
      int main(int argc, char **argv)
      {
          FOO_FUNC *pFoo = (FOO_FUNC *)malloc(sizeof(FOO_FUNC) * 2);
          pFoo[0] = &a;
          pFoo[1] = &b;
      
          pFoo[0](10);
          pFoo[1](20);
      
          return 0;
      }
      

      【讨论】:

      【解决方案4】:

      从我的头顶,未经测试。

      // create array of pointers to functions
      void (*functions[256])(void) = {&function0, &function1, &function2, ..., };
      
      // copy pointers to struct
      int i;
      for (i = 0; i < 256; i++) struct.functions[i] = functions[i];
      

      编辑:更正了 Chris Lutz 所说的语法错误。

      【讨论】:

        【解决方案5】:

        您可以在声明结构实例时这样做:

        function_structur fs = { struct_field1,
                                 struct_field2,
                                 {function0, function1, ..., function255},
                                 struct_field3,
                                 ... };
        

        在声明数组后,您不能使用此快捷方式来初始化数组:如果需要这样做,则必须动态执行(使用循环、memcpy 或其他方式)。

        【讨论】:

          【解决方案6】:

          如果您想发布-使用{func1, func2, ...} 之类的形式初始化数组,可以通过以下方式完成(使用 GCC):

          UPD(感谢Chris Lutz的评论)

          像这样定义一个宏:

          #define FUNCTION_VECTOR_COPY(destVec, sourceVec) memcpy(destVec, sourceVec, sizeof(sourceVec))
          

          并使用Compound Literals传递源向量,如下:

          #include <string.h>
          ...
          void (*functions[256])();
          ...
          FUNCTION_VECTOR_COPY (functions, ((void(*[])()) {func1, func2, func3}));
          

          【讨论】:

          • sizeof(funcsFrom) 在这里无效。函数参数中的数组衰减为指针,因此您的函数实际上是void setFuncs(void(**funcsTo)(), void(**funcsFrom)()),没有关于sizeof 的信息。您应该 a) 使用允许您这样做的宏,或者 b) 将数组大小作为第三个参数传递。如果你这样做 b,你甚至可以 c) 编写一个包装宏,它会根据 sizeof 第二个参数自动插入第三个参数。此外,d) 使用 sizeof(funcsFrom) / sizeof(funcsFrom[0]) 以防类型发生变化,并且 e) 您的函数在其他方面与 memcpy 相同。
          • @Chris 感谢您的重要评论,我只测试了 2 个值,这就是我错过 sizeof 问题的原因。 (一个了不起的!; (d) - 好的,但是您应该首先检查源向量的大小是否大于 0; (e) - 是的,但你不应该忘记包含string.h。查看更新的答案。
          猜你喜欢
          • 2011-07-26
          • 2021-12-05
          • 1970-01-01
          • 2012-09-11
          • 2015-12-01
          • 1970-01-01
          • 2012-07-27
          • 2018-11-01
          • 1970-01-01
          相关资源
          最近更新 更多