C:如何将一系列变量应用于函数?

时间:2009-10-08 16:12:23

标签: c apply

在C中,有没有办法调用存储在某个数组中的参数的函数?我是C新手,我甚至不确定这是不对的,例如:

void f0(int a) { ... };
void f1(int a, int b) { ... };
void f2(int a, int b, int c) { ... };

int array[5][2][?] = [
    [&f0, [5]],
    [&f1, [-23, 5]],
    [&f2, [0, 1, 2]],
    [&f2, [1235, 111, 4234]],
    [&f0, [22]]
];

int i;
for (i = 0; i < 5; i++) {
    APPLY?(array[i][0], array[i][1])
}

PS:当阵列的项目长度不同时,我应该使用什么样的结构?

在Python中,这将是:

def f0(a): ...
def f1(a, b): ...
def f2(a, b, c): ...

array = [
    (f0, (5,)),
    (f1, (-23, 5)),
    (f2, (0, 1, 2)),
    (f2, (1235, 111, 4234)),
    (f0, (22,))
]

for f, args in array:
    apply(f, args)

5 个答案:

答案 0 :(得分:2)

不是,不。

在C中更好的方法是将所有函数定义为具有相同的签名,例如:

void f0(int size, int elements[])

然后将适当大小的数组传递给函数。

// this is a function pointer
void (*x)(int, int[]); 
...
// set x to point at f0
x = f0;
// call x (ie: f0) with 1 element from position 5 of array
x(1, &(array[5]));

答案 1 :(得分:2)

可能在C中有可变的arity函数,但机制很笨并且有一定的限制,即必须至少有一个固定参数,并且你需要能够从固定参数或变量中分辨出来参数本身在变量列表的末尾。

一个更典型的解决方案,就是充当C的优势而不是弱点,就像这个例子。 (更新了函数指针。)

#include <stdio.h>

void f1(int, int *);
void f2(int, int *);

struct BoxOfInts {
    void (*f)(int,int *);
    int howMany;
    int theNumbers[4];
} intMachine[] = {
    {f1, 1,  { 5,  }},
    {f2, 2,  { -23, 5  }},
    {f1, 3,  { 0, 1, 2  }},
    {f2, 3,  { 1235, 111, 4234  }},
    {f1, 1,  { 22,  }},
    { 0 }
};

void dispatch(void)
{
    for(struct BoxOfInts *p = intMachine; p->f; ++p)
        (*p->f)(p->howMany, p->theNumbers);
}

void f1(int howMany, int *p)
{
    while (howMany-- > 0) {
        int t = *p++;
        printf("f1 %d %d\n", howMany, t);
    }
}

void f2(int howMany, int *p)
{
    while (howMany-- > 0) {
        int t = *p++;
        printf("f2 %d %d\n", howMany, t);
    }
}

int main()
{
  dispatch();
  return 0;
}

答案 2 :(得分:0)

我想也许你只想要:

array[i][0](array[i][1]);

要从C中的指针调用函数,只需要函数调用运算符,即括号。

可能有用的链接:http://boredzo.org/pointers/

答案 3 :(得分:0)

c没有内置的列表概念或list comprehension,您必须在数组上设置显式循环,并且必须自己支持列表的长度。

是的,这比python方式更啰嗦,但那是因为python正在为你处理细节。

非常适合处理名义“清单”的数据结构:

  • 动态数组(可能包含在struct中,以便在同一位置保存当前长度和分配长度等元信息)
  • linked lists

如果您选择基于阵列的解决方案,则需要

  1. 跟踪当前长度并将其传递给处理函数
  2. 使用标记来标记数据的结尾(这可能意味着使用更大的数据类型,以允许您指定无法在数据中显示的标记)
  3. 链接列表可以逐节点处理,因为它具有自然的结束。

答案 4 :(得分:0)

#include <stdio.h> 

void f0(int a              ){ printf("f0(%i)\n",      a    ); }
void f1(int a, int b       ){ printf("f1(%i,%i)\n",   a,b  ); }
void f2(int a, int b, int c){ printf("f2(%i,%i,%i)\n",a,b,c); }

typedef void (*f_arg1)(int);
typedef void (*f_arg2)(int,int);
typedef void (*f_arg3)(int,int,int);

struct fn_call {
  f_arg1 fn;
  int arg_num;
  int *args;
} array[] = {  { (f_arg1)f0, 1, (int[]){5}               },
               { (f_arg1)f1, 2, (int[]){-23, 5}          },
               { (f_arg1)f2, 3, (int[]){0, 1, 2}         },
               { (f_arg1)f2, 3, (int[]){1235, 111, 4234} },
               { (f_arg1)f0, 1, (int[]){22}              }   };

void apply( struct fn_call *call ){
  switch( call->arg_num ){
  case 1: ((f_arg1)call->fn)( call->args[0] );                  break;
  case 2: ((f_arg2)call->fn)( call->args[0], call->args[1] );   break;
  case 3: ((f_arg3)call->fn)( call->args[0], call->args[1], call->args[2] );
  }
}

int main(){
  for(unsigned i=0; i<sizeof(array); i++)  apply( &array[i] );
}

结果:

f0(5)
f1(-23,5)
f2(0,1,2)
f2(1235,111,4234)
f0(22)